栈:是限定仅在表尾进行插入与删除操作的线性表。我们把允许插入与删除的一端称为栈顶,另一端称为栈底,不含任何数据元素的称为空栈。栈的插入操作,叫作进栈,也叫压栈、入栈,类似于子弹入弹夹;栈的删除操作,叫作出栈,也叫弹栈,如同弹夹中的子弹出夹。注意:栈的定义中的“表尾”指的是“栈顶”,而不是“栈底”。
首先,栈是一个线性表,也就是说:栈具有线性结构,即前驱后继关系;只不过它是一个特殊的线性表而已,它的特殊之处在于限制了这个线性表的插入与删除位置,它始终只在栈顶进行插入与删除操作;这也就使得,栈底是固定的,最先进栈的只能待在栈底,而出栈时,后面进栈的反而可以先出去;因此,栈又被称为“后进先出”的线性表。
栈的顺序存储,我们一般简称为“线性栈”。我们把数组下标为0的一端作为栈底,因为首元素都存在栈底,变化最小,所以让它作栈底。同时,通过定义一个top变量来指示栈顶元素在数组中的位置,若存储栈的长度为StackSize,则栈顶位置top必须小于StackSize;当栈存在一个元素时,top等于0;通常我们把空栈的判定条件定为“top是否等于-1”,是即为空栈,否即不是。下面进行顺序栈的插入与删除操作,具体操作源代码如下所示:
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 #define OK 1 5 #define ERROR 0 6 #define TRUE 1 7 #define FALSE 0 8 9 #define MAXSIZE 100 /* 存储空间初始分配量 */ 10 11 typedef int Status; 12 typedef int SElemType; /* SElemType类型根据实际情况而定,这里假设为int */ 13 14 /* 顺序栈结构 */ 15 typedef struct 16 { 17 SElemType data[MAXSIZE]; 18 int top; /* 用于栈顶指针 */ 19 }SqStack; 20 21 Status visit(SElemType c) 22 { 23 printf("%d ",c); 24 return OK; 25 } 26 27 /* 构造一个空栈S */ 28 Status InitStack(SqStack *S) 29 { 30 S->top=-1; 31 return OK; 32 } 33 34 /* 把S置为空栈 */ 35 Status ClearStack(SqStack *S) 36 { 37 S->top=-1; 38 return OK; 39 } 40 41 /* 返回S的元素个数,即栈的长度 */ 42 int StackLength(SqStack S) 43 { 44 return S.top+1; 45 } 46 47 /* 插入元素e为新的栈顶元素 */ 48 Status Push(SqStack *S,SElemType e) 49 { 50 if(S->top == MAXSIZE -1) /* 栈满 */ 51 { 52 return ERROR; 53 } 54 S->top++; /* 栈顶指针增加一 */ 55 S->data[S->top]=e; /* 将新插入元素赋值给栈顶空间 */ 56 57 return OK; 58 } 59 60 /* 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR */ 61 Status Pop(SqStack *S,SElemType *e) 62 { 63 if(S->top==-1) 64 return ERROR; 65 *e=S->data[S->top]; /* 将要删除的栈顶元素赋值给e */ 66 S->top--; /* 栈顶指针减一 */ 67 68 return OK; 69 } 70 71 /* 从栈底到栈顶依次对栈中每个元素显示 */ 72 Status StackTraverse(SqStack S) 73 { 74 int i; 75 i=0; 76 while(i<=S.top) 77 { 78 visit(S.data[i++]); 79 } 80 printf(" "); 81 82 return OK; 83 } 84 85 int main() 86 { 87 int j,e; 88 SqStack s; 89 90 if(InitStack(&s)==OK) 91 for(j=1;j<=10;j++) 92 Push(&s,j); 93 printf("1.栈中元素依次为:"); 94 StackTraverse(s); 95 96 Pop(&s,&e); 97 printf("2.弹出的栈顶元素 e=%d ",e); 98 printf("3.弹出栈顶元素 e=%d 后,栈的长度为 %d ",e,StackLength(s)); 99 100 Pop(&s,&e); 101 printf("4.弹出的下一个栈顶元素 e=%d ",e); 102 printf("5.栈中元素依次为:"); 103 StackTraverse(s); 104 105 Push(&s,11); 106 printf("6.插入新栈顶元素 e=%d 后,栈的长度为 %d ",11,StackLength(s)); 107 printf("7.栈中元素依次为:"); 108 StackTraverse(s); 109 110 ClearStack(&s); 111 printf("8.清空栈后,栈的长度为 %d ",StackLength(s)); 112 113 return 0; 114 }