栈(Stack)是限定只能在表的一端进行插入和删除操作的线性表。在表中,允许插入和删除的一端称作“栈顶(top)”,不允许插入和删除的另一端称作“栈底(bottom)”。
通常称往栈顶插入元素的操作为“入栈”,称删除栈顶元素的操作为“出栈”。因为后入栈的元素先于先入栈的元素出栈,故被称为是一种“后进先出”的结构,因此又称 LIFO 表(Last In First Out的缩写)。
和线性表类似,栈也有两种存储表示:顺序栈和链栈。
顺序存储结构简称为顺序栈。和顺序表类似,对顺序栈也需要事先为它分配一个可以容纳最多元素的存储空间。用图表示顺序栈如下:
链栈即为栈的链式存储结构。
顺序栈的实现依靠数组,而数组需要事先声明长度,一次性地静态地分配内存空间。这样就给我们带来很多不便。因为我们事先并不能精确地估计栈所需的大小,估计大了浪费空间,估计小了后果就严重了,导致程序无法正常运行。所以我们通常使用链栈这种数据结构。
链栈用链表作为存储结构,栈初始化时仅需给栈顶指针分配内存空间,而后每当有数据入栈时再为该数据分配空间,这样实现了内存空间的动态分配。理论上栈的大小可以是无限大的(小心撑爆你的内存 o(∩_∩)o)。不存在顺序栈的诸多问题。
模板:
1 #include<stdio.h> 2 #include<string.h> 3 #include<stdlib.h> 4 struct node 5 { 6 int data; 7 struct node *next; 8 }; 9 int push(node *top,int e) //进栈 10 { 11 node *p; 12 p=(node *)malloc(sizeof(node)); 13 p->data=e; 14 p->next=top->next; 15 top->next=p; 16 return (1); 17 } 18 int gettop(node *top) //栈顶元素 19 { 20 if(top->next==NULL) 21 { 22 printf("栈是空的 "); 23 return 0; 24 } 25 return (top->next->data); 26 } 27 int pop(node *top) //出栈 28 { 29 node *p; 30 int y; 31 p=top->next; 32 if(p==NULL) 33 { 34 printf("出栈失败,栈是空栈 "); 35 return (0); 36 } 37 y=p->data; 38 top->next=p->next; 39 free(p); 40 return (y); 41 } 42 int main() 43 { 44 node *top; 45 int e,a; 46 top=(node *)malloc(sizeof(node)); 47 if(!top) 48 printf("error "); 49 top->next=NULL; 50 printf(" /***********************/ "); 51 printf(" /* 链栈的表示和实现 */ "); 52 printf(" /***********************/ "); 53 do 54 { 55 printf(" /**********************/ "); 56 printf(" /* 菜单 */ "); 57 printf(" 1、进栈 2、取栈顶元素 3、出栈 0、结束 "); 58 printf(" /**********************/ "); 59 printf(" 请输入你的选择: "); 60 scanf("%d",&a); 61 switch(a) 62 { 63 case 1:{ 64 printf("请输入你要进栈的元素: "); 65 scanf("%d",&e); 66 push(top,e); 67 break; 68 } 69 case 2: 70 { 71 printf("栈顶元素为:%d ",gettop(top)); 72 break; 73 } 74 case 3: 75 { 76 printf("出栈返回值为%d: ",pop(top)); 77 break; 78 } 79 default: 80 { 81 printf("输入不符合要求,请重新输入: "); 82 break; 83 } 84 } 85 }while(a!=0); 86 return 0; 87 } 88
例题:(sdut 1479)
数据结构实验之栈:行编辑器
Time Limit: 1000ms Memory limit: 65536K 有疑问?点这里^_^
题目描述
一个简单的行编辑程序的功能是:接受用户从终端输入的程序或数据,并存入用户的数据区。
由于用户在终端上进行输入时,不能保证不出差错,因此,若在编辑程序中,“每接受一个字符即存入用户数据区”的做法显然不是最恰当的。较好的做法是,设立一个输入缓冲区,用以接受用户输入的一行字符,然后逐行存入用户数据区。允许用户输入出差错,并在发现有误时可以及时更正。例如,当用户发现刚刚键入的一个字符是错的时,可补进一个退格符"#",以表示前一个字符无效;
如果发现当前键入的行内差错较多或难以补救,则可以键入一个退行符"@",以表示当前行中的字符均无效。
如果已经在行首继续输入'#'符号无效。
输入
输入一个多行的字符序列。但行字符总数(包含退格符和退行符)不大于250。
输出
按照上述说明得到的输出。
示例输入
whli##ilr#e(s#*s) outcha@putchar(*s=#++);
示例输出
while(*s) putchar(*s++);
1 #include<stdio.h> 2 #include<string.h> 3 #include<stdlib.h> 4 typedef struct Node 5 { 6 char data; 7 struct Node *next; 8 }node; 9 void push(node *top,char e) 10 { 11 node *p; 12 p=(node *)malloc(sizeof(node)); 13 p->data=e; 14 p->next=top->next; 15 top->next=p; 16 } 17 void pop(node *top) 18 { 19 node *p; 20 p=top->next; 21 top->next=p->next; 22 free(p); 23 } 24 void list(node *top) 25 { 26 node *p; 27 p=top->next; 28 while(p->next!=NULL) 29 { 30 printf("%c",p->data); 31 p=p->next; 32 } 33 printf("%c",p->data); 34 } 35 node *popt(node *top) 36 { 37 node *p,*q; 38 p=top->next; 39 top->next=NULL; 40 q=p->next; 41 while(p!=NULL) 42 { 43 p->next=top->next; 44 top->next=p; 45 p=q; 46 if(q!=NULL) q=q->next; 47 } 48 return top; 49 } 50 int main() 51 { 52 node *top; 53 int len,i; 54 char b[10000]; 55 while(~scanf("%s",b)) 56 { 57 top=(node *)malloc(sizeof(node)); 58 top->next=NULL; 59 len=strlen(b); 60 for(i=0;i<len;i++) 61 { 62 if(b[i]=='@') 63 top->next=NULL; 64 else if(b[i]=='#') 65 { 66 if(top->next!=NULL) 67 pop(top); 68 } 69 else push(top,b[i]); 70 } 71 if(top->next!=NULL) 72 { 73 top=popt(top); 74 list(top); 75 printf(" "); 76 } 77 } 78 return 0; 79 } 80 81