【学习笔记】关于栈与单调栈,你需要知道这些!(C语言实现)

基本概念


  1. 栈是一种后进先出(LIFO)的数据结构。
  2. 对于栈来说,表尾端称为栈顶(top),表头端称为栈低(bottom)。
  3. 所有元素只能从栈顶进入,进入栈的操作称为入栈(压栈)。
  4. 同时所有元素只能从栈顶弹出,弹出栈的操作称为出栈(弹栈)。
  5. 因为只能对栈顶元素进行操作,因此不支持对栈内元素进行随机访问,即我们不能在任意位置访问栈内元素,只能从栈顶访问。

压栈入栈图片演示


【学习笔记】关于栈与单调栈,你需要知道这些!(C语言实现)_第1张图片

栈能解决的问题


​ 在实际应用中,栈的应用场景还是很多的。比如浏览器的后退、上一步功能,一些软件的撤销功能,计算器,Linux的文件路径等,都是有栈的辅助来实现的。

​ OJ题常见的最经典的题莫过于:LeetCode 20. 有效的括号 、LeetCode 224. 基本计算器,相信解决了这两道题会对栈有更深刻的理解。

​ 此外,如果学过树的遍历方式的朋友,可能也知道除了递归遍历树,也可以用栈辅助递推遍历树。所以栈也是一种由递归转化为递推的一种优秀的辅助数据结构。

栈的基本操作


  1. 栈顶指针:指向栈顶下标。
  2. 入栈:即将元素放入栈顶,同时栈顶指针+1,注意要判断栈是否满,如果是则需要将栈扩容或者禁止入栈。
  3. 出栈:即将栈顶元素弹出,同时栈顶指针-1,注意要判断栈是否为空,如果空栈仍然出栈会报错。
  4. 判断栈是否为空:返回是或否。
  5. 计算栈中元素数量:返回栈中元素数量。

代码


#include
#include
//自定义栈结构
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))

单调栈的基本操作

  • 入栈:循环判断栈顶元素是否大于(等于)(或小于(等于))将要入栈的元素,如果是则将栈顶元素出栈,否则入栈并退出循环。
  • 其他操作和栈的操作相同

图解维护单调栈:

【学习笔记】关于栈与单调栈,你需要知道这些!(C语言实现)_第2张图片


单调栈能解决的问题

单调栈这个结构有什么用呢?做了这么多的题,本蒟蒻归纳总结了一下几类问题:

  1. 返回数组当前下标以后比当前下标元素大(小)的所有元素:见例题 LeetCode 739. 每日温度
  2. 返回数组当前下标元素前后第一个比其大(小)的元素及其下标:503. 下一个更大元素 II 、 LeetCode 84. 柱状图中最大的矩形
  3. 寻找数组中的极大值(极小值)及其所在下标:见例题 456. 132 模式 、 42. 接雨水

这个单调栈,看似简单,实际如果深究其特性,还能整出这么多花来,真的太佩服了(已经被虐哭了QAQ)。

对于单调栈的题,个人感觉还是要多练,才能掌握单调栈的特性。


相关题目

  • LeetCode1124. 表现良好的最长时间段
  • LeetCode 5881. 增量元素之间的最大差值

参考资料

你可能感兴趣的:(#,数据结构笔记,c语言,数据结构,栈)