栈
基本概念
- 栈是一种后进先出(LIFO)的数据结构。
- 对于栈来说,表尾端称为栈顶(top),表头端称为栈低(bottom)。
- 所有元素只能从栈顶进入,进入栈的操作称为入栈(压栈)。
- 同时所有元素只能从栈顶弹出,弹出栈的操作称为出栈(弹栈)。
- 因为只能对栈顶元素进行操作,因此不支持对栈内元素进行随机访问,即我们不能在任意位置访问栈内元素,只能从栈顶访问。
压栈入栈图片演示
栈能解决的问题
在实际应用中,栈的应用场景还是很多的。比如浏览器的后退、上一步功能,一些软件的撤销功能,计算器,Linux的文件路径等,都是有栈的辅助来实现的。
OJ题常见的最经典的题莫过于:LeetCode 20. 有效的括号 、LeetCode 224. 基本计算器,相信解决了这两道题会对栈有更深刻的理解。
此外,如果学过树的遍历方式的朋友,可能也知道除了递归遍历树,也可以用栈辅助递推遍历树。所以栈也是一种由递归转化为递推的一种优秀的辅助数据结构。
栈的基本操作
- 栈顶指针:指向栈顶下标。
- 入栈:即将元素放入栈顶,同时栈顶指针+1,注意要判断栈是否满,如果是则需要将栈扩容或者禁止入栈。
- 出栈:即将栈顶元素弹出,同时栈顶指针-1,注意要判断栈是否为空,如果空栈仍然出栈会报错。
- 判断栈是否为空:返回是或否。
- 计算栈中元素数量:返回栈中元素数量。
代码
#include<stdio.h>
#include<stdlib.h>
//自定义栈结构
typedef struct mystack
{
int num;//记录元素数量
int size;//记录栈大小
int* data;//数据区
int top;//栈顶指针
}mystack;
//初始化栈
mystack* initstack(int num)
{
mystack* s = (mystack*)malloc(sizeof(mystack));
s -> data = (int*) malloc(sizeof(int) * num);
s -> num = 0;
s -> size = num;
}
//出栈
int stack_pop(mystack* s)
{
return s -> data[--s -> top];
}
//入栈,返回值:1表示正常,0表示失败
int stack_push(mystack* s, int val)
{
if(s -> top == s -> size) return 0;
s -> data[s -> top++] = val;
return 1;
}
//判断栈是否为空,返回值:1表示真,0表示假
int stack_empty(mystack* s)
{
return s -> top == 0;
}
//计算栈中元素
int stack_size(mystack* s)
{
return s -> top;
}
int main()
{
mystack* st = initstack(10);
stack_push(st, 5);
stack_push(st, 4);
stack_push(st, 3);
stack_push(st, 2);
stack_push(st, 1);
while(!stack_empty(st))
{
printf("弹出栈顶元素,值为:%d\n", stack_pop(st));
}
return 0;
}
相关题目
-
LeetCode 71. 简化路径
-
LeetCode 150. 逆波兰表达式求值
-
LeetCode 232. 用栈实现队列
-
LeetCode 144. 二叉树的前序遍历
-
LeetCode 94. 二叉树的中序遍历
-
LeetCode 145. 二叉树的后序遍历
单调栈
基本概念
- 我们有这么一个栈,栈内元素要么(非严格)单调递增,要么(非严格)单调递减,那么这个栈就是单调栈
- (没了,就这么朴实无华且枯燥你敢信(bushi))
单调栈的基本操作
- 入栈:循环判断栈顶元素是否大于(等于)(或小于(等于))将要入栈的元素,如果是则将栈顶元素出栈,否则入栈并退出循环。
- 其他操作和栈的操作相同
图解维护单调栈:
单调栈能解决的问题
单调栈这个结构有什么用呢?做了这么多的题,本蒟蒻归纳总结了一下几类问题:
- 返回数组当前下标以后比当前下标元素大(小)的所有元素:见例题 LeetCode 739. 每日温度
- 返回数组当前下标元素前后第一个比其大(小)的元素及其下标:503. 下一个更大元素 II 、 LeetCode 84. 柱状图中最大的矩形
- 寻找数组中的极大值(极小值)及其所在下标:见例题 456. 132 模式 、 42. 接雨水
这个单调栈,看似简单,实际如果深究其特性,还能整出这么多花来,真的太佩服了(已经被虐哭了QAQ)。
对于单调栈的题,个人感觉还是要多练,才能掌握单调栈的特性。
相关题目
参考资料
无