1.栈(Stack)是限制在表的一端进行插入和删除操作的线性表。允许进行插入、删除操作的这一端称为栈顶(Top),另一个固定端称为栈底。当表中没有元素时称为空栈。如图所示的栈中有三个元素,进栈的顺序是a1、a2、a3,当需要出栈时其顺序为a3、a2、a1,所以栈又称为“后进先出”(Last-In First-Out,LIFO)或“先进后出”(First-In Last-Out,FILO)的线性表,简称“LIFO表”或“FILO表”。
2.顺序栈
栈顶指针top与栈中数据元素的关系如图所示,其中图(a)为空栈,图(c)是A、B、C、D、E 5个元素依次入栈之后栈的状态及栈顶指针所指位置,图(d)是在图(c)之后E、D相继出栈,此时,栈中还有3个元素,或许最近出栈的元素D、E仍然在原先的单元存储中,但由于top指针已经指向了新的栈顶,则存储D、E的单元已经属于无效数据,意味着元素D、E已不在栈中了,通过这个示意图要深刻理解栈顶指针的作用。
对上述存储结构基本操作的实现如下。
(1)置空栈:首先建立栈空间,然后初始化栈顶指针。

SeqStack *Init_SeqStack( )
{ SeqStack *s;
S=malloc(sizeof(SeqStack));
s->top= -1; return s;
}
(2)判空栈。

int Empty_SeqStack(SeqStack *s)
{ if (s->top==-1) return 1;
else return 0;
}
(3)入栈。

int Push_SeqStack (SeqStack *s, datatype x)
{ if (s->topMAXSIZE-1) return 0; /栈满不能入栈/
else { s->top++;
s->data[s->top]=x;
return 1;
}
}
(4)出栈。

int Pop_SeqStack(SeqStack *s, datatype *x)
{ if (Empty_SeqStack ( s ) ) return 0; /*栈空不能出栈 */
else { *x=s->data[s->top];
s->top–; return 1;
} / * 栈顶元素存入 * x,返回 */
}
(5)取栈顶元素。

datatype Top_SeqStack(SeqStack *s)
{ if ( Empty_SeqStack ( s ) ) return 0; / * 栈空 */
else return (s->data[s->top] );
}
两点说明:
① 对于顺序栈,入栈时,首先判断栈是否满了,栈满的条件为s->topMAXSIZE-1,栈满时,不能入栈,否则会出现空间溢出,引起错误,这种现象称为上溢。
② 出栈和读栈顶元素操作,先判断栈是否为空,为空时不能操作,否则会产生错误。通常栈空时常作为一种控制转移的条件
3.链栈
用链式存储结构实现的栈称为链栈。通常链栈用单链表表示,因此其结点结构与单链表的结点结构相同,在此用LinkStack表示,即有:

typedef struct node
{ datatype data;
struct node *next;
} StackNode * LinkStack;
说明:top为栈顶指针,即LinkStack top。
因为栈中的主要运算是在栈顶插入、删除的,显然选链表的头部做栈顶是最方便的,而且没有必要像单链表那样为了运算方便附加一个头结点。通常将链栈表示为图所示的形式。
链栈基本操作的实现如下:
(1)置空栈。
LinkStack Init_LinkStack( )
{ return NULL;
}
(2)判栈空。

int Empty_LinkStack(LinkStack top)
{ if (topNULL) return 1;
else return 0;
}
(3)入栈。

LinkStack Push_LinkStack(LinkStack top, datatype x)
{ StackNode *s;
s=malloc(sizeof(StackNode));
s ->data=x; s ->next=top; top=s;
return top;
}
(4)出栈。

LinkStack Pop_LinkStack (LinkStack top, datatype *x)
{ StackNode *p;
if (topNULL) return NULL;
else { *x=top->data; p=top; top=top->next; free §;
return top;
}
}