![aa7ed2298a6b6d0d4a145c584f634038.png](https://i-blog.csdnimg.cn/blog_migrate/355c408047a8591e6c8848e71d9b0576.png)
栈的基本概念
栈(Stack):只允许在一端进行插入或删除操作的线性表
栈是一种受限的线性表,受限体现在只能在一端进行操作
![bedfddb663967d949016d841ebd6b5ee.png](https://i-blog.csdnimg.cn/blog_migrate/922ec29cf0e1b3e4df81e8c10b86d70d.png)
栈是一种后进先出(LIFO)的数据结构
进栈的顺序为a1,a2,a3,a4,a5,出栈的顺序为a5,a4,a3,a2,a1
栈的顺序存储
![574b8a4ba9ef0b1fad3caced9e1bbc0d.png](https://i-blog.csdnimg.cn/blog_migrate/b59ddbcac12f24f133f7af158aaaafa3.jpeg)
顺序栈的定义
#define MaxSize 50
typedef struct {
ElemType data[MaxSize];
int top;
}SqStack;
- 栈空的条件:S.top==-1
- 栈长:S.top+1
- 栈满的条件:S.top==MaxSize-1
注意:
- S.top为栈顶指针,使用时作为数组下标
- 栈元素序号从1开始,数组序号从0开始,因此序号相差1
栈的初始化
void initStack(SqStack &S)
{
S.top = -1; //初始化栈顶指针
}
栈的初始化只需要将栈顶指针初始化为-1,由于需要修改栈,故形参用引用类型
判断栈空
bool StackEmpty(SqStack S)
{
if (S.top == -1) //栈空
return true;
else
return false; //栈不空
}
判断栈是否为空只需判断栈顶指针是否为-1
入栈操作
bool Push(SqStack& S, ElemType x)
{
if (S.top == MaxSize - 1) //栈满 不能执行入栈操作
return false;
S.top++; //指针先加1,再入栈
S.data[S.top] = x;
return true;
}
进栈之前先判断栈是否为满,栈满则不能执行入栈操作
出栈操作
bool Pop(SqStack& S, ElemType& x)
{
if (S.top == -1) //栈空 不能执行出栈操作
return false;
x = S.data[S.top]; //先出栈 指针再减1
S.top--;
return true;
}
出栈之前先判断栈是否为空,栈空则不能执行出栈操作。
需要修改变量x的值,故也设为引用类型的形参
![f9dda9c5b529eeb58b9a4de21682de69.png](https://i-blog.csdnimg.cn/blog_migrate/0ae51bd3e20ca93d8e748504196423ff.jpeg)
出栈操作结果是使得栈中元素减一,数组中元素并未减少
读栈顶元素
bool GetPop(SqStack S, ElemType& x)
{
if (S.top == -1) //栈空报错
return false;
x = S.data[S.top]; //用x存储栈顶元素
return true;
}
读栈顶元素与出栈操作类似,只是不需要移动栈顶指针
共享栈
共享栈:将两个栈底设置在共享空间的两端,栈顶向空间中间延伸
(相当于将两个杯子的杯口拼在一起)
![7c7aa0cb8d6b1d7aa9a3328ae7ae234d.png](https://i-blog.csdnimg.cn/blog_migrate/630f3688204579839c9d0492bef8c845.jpeg)
栈空条件:0号栈top==-1 1号栈top==MaxSize
栈满条件:top1-top0==1
共享栈的优点是使得空间利用更加有效,而存取时间复杂度仍为O(1)
栈的链式存储结构
链栈:采用链式存储的栈
![df3ffeaa0681a75fc61afb43413ed473.png](https://i-blog.csdnimg.cn/blog_migrate/a1277598eaec03b12a42f030cb55cc84.png)
单链表的头结点作为栈顶结点,尾结点作为栈底结点
typedef struct Linknode {
ElemType data;
struct Linknode* next;
}LiStack;
由于头结点作为栈顶结点,故一切操作均在表头进行
链栈的出栈入栈操作对应于单链表的插入与删除,不过均在单链表的表头进行,其余操作与单链表的操作类似。