本文主要内容:本文主要讲解栈的基本概念、基本操作和栈的顺序、链式实现。
栈
一、栈的基本概念
1、基本概念
栈是只允许在一端进行插入或删除操作的线性表。
栈顶:线性表允许进行插入和删除的一端
栈底:不允许进行插入和删除的另一端
空栈:不含任何元素的空表
假设某个栈S=(a1,a2,a3,a4,a5),如下图所示,则a1为栈底元素,a5为栈顶元素。由于栈只能在栈顶进行插入和删除操作,所以S的进栈次序为a1,a2,a3,a4,a5,出栈次序为a5,a4,a3,a2,a1。栈的操作特性为后进先出(LIFO)。
n个不同元素进栈,出栈元素有↓,下述公式成为卡特兰数。
( 1 / ( n + 1 ) ) ∗ C 2 n n . \ (1/(n+1))*C^{n}_{2n}\,. (1/(n+1))∗C2nn.
2、基本操作
InitStack(&S);//初始化一个空栈S
StackEmpty(S);//判断一个栈是否为空,若栈S为空则返回true,否则返回false
Push(&S,x);//进栈,若栈S未满,则将x加入使之成为新栈顶
Pop(&S,&x);//出栈,若栈非空,则弹出栈顶元素,并用x返回
GetTop(S,&x);//读栈顶元素,若栈S非空,则用x返回栈顶元素
DestroyStack(&S);//销毁栈,并释放栈S占用的存储空间(&表示引用调用)
注意:只要题干没有特别表明,基本操作对应的函数可以直接使用。
二、栈的顺序存储结构
因为栈本质上是一种操作受限的线性表,所以它也有两种存储方式——顺序存储和链式存储。
1、顺序栈的实现
采用顺序存储的栈称为顺序栈,它利用一组地址连续的存储单元存放自栈底到栈顶的数据元素,同时附设一个指针(top)来指示当前栈顶元素的位置。
栈顶顺序存储类型为:
#define MaxSize 50//定义栈中元素的最大个数
typedef struct{
Elemtype data[MaxSize];//存放栈中元素
int top;//栈顶元素
}SqStack;
栈顶指针:S.top,初始时设置S.top=-1
栈顶元素:S.data[S.top]
进栈操作:栈不满时,栈顶指针先加1,再送值到栈顶元素
栈空条件:S.top==-1
栈满条件:S.top==MaxSize-1
栈长:S.top+1
顺序栈的入栈操作受数组上界的约束,当对栈的最大使用空间估计不足时,有可能发生栈上溢。
2、顺序栈的基本运算
顺序栈上常用的基本运算的实现如下:
1)初始化
void InitStack(SqStack &S){
S.top=-1//初始化栈顶指针
}
2)判栈空
bool StackEmpty(SqStack S){
if(S.top=-1) return true;//栈空
else return false;//栈非空
}
3)进栈
bool Push(SqStack &S,ElemType x){
if(S.top==MaxSize-1) return false;//栈满
S.data[++S.top]=x;//栈顶指针+1,x进栈
return true;
}
4)出栈
bool Pop(SqStack &S,ElemType &x){
if(S.top==-1) return false;//栈空
x=S.data[S.top--];//元素出栈,栈顶指针-1
return true;
}
5)读栈顶元素
bool GetTop(SqStack s,ElemType &x){
if(S.top==-1) return false;//栈空
x=S.data[S.top];//用x记录栈顶元素
}
3、共享栈
因为栈底位置相对不变,可以让两个顺序栈共享一个一维数组,将两个栈的栈底分别设置在共享空间的两端,两个栈顶向共享空间中间延伸。
栈空:top1=-1时0号栈为空,top2=MaxSize时1号栈为空
栈满:top2-top1=1时,栈满
入栈:top1先+1再赋值,top2先-1再赋值
出栈:top1-1,top2+1
三、栈的链式存储结构
采用链式存储的栈称为链栈,链栈的优点是便于多个栈共享存储空间和提高其效率,且不存在栈满上溢的情况。通常采用单链表实现,并规定所有操作都是在单链表的表头进行的。规定链栈没有头结点,Lhead指向栈顶元素。如下图所示:
采用链栈存储,便于结点的插入与删除。链栈的操作与链表类似,入栈和出栈的操作都在链表的表头进行。
另有操作受限的线性表——队列见链接:【待补充】
本文内容为个人学习总结所得,如有问题欢迎讨论和指正。