算法——栈和队列

栈概述

这里描述的是数据结构的栈,是物理栈结构的一个抽象数据类型。模仿了栈结构的特点,而做出一系列的动作。

物理中栈的本质 就是内存中的一个区域。他的特殊之处就在于,CPU从中存取数据的方式。就好像弹夹装子弹,就是先入后出,后入先出

对于堆栈而言,如果栈顶和栈底重合,那么表示栈里面没有数据。如果需要往栈里面存放数据那么栈顶指针就往上挪一挪,然后将要存储的数据存放在栈顶 的位置。这个动作就叫做压栈\入栈 。当需要从栈中取出数据的时候,就先将数据保存到寄存器当中,然后栈顶往下挪 ,这个动作就叫做弹栈\出栈。但是要注意,出栈了以后,数据还是在堆栈中,只是这个数据就被当成了垃圾。

应用

重点是在题目中应用栈的结构思想。做题时,多数使用数组直接模拟栈或直接用C++ STL中的stack

一般是应付左右匹配类的题

栈的结构思想:

  • 一边压栈的同时一边检测是否需要出栈,出栈永远是刚刚后进的数据(会连续出栈)
  • 误区:
    • 对于一组数据不是先一股脑全部压栈再出栈,而是一边压栈一边有选择地出栈

题目

洛谷P4387

验证栈序列

思路:用栈模拟

按入栈顺序入栈,如果栈顶元素与出栈序列的元素相同,就将其弹出。

首先将入栈序列的第i个元素压到"stack"中,(i,j分别是入栈序列和出栈序列的下标)

判断(注意用while判断,因为可能连续弹出)"stack"中的栈顶元素是否和出栈序列中的第i个元素一致(栈为空就不用判断了)如果一致则弹出栈顶元素,j++;如果不致则继续压入入栈序列中的第i+1个元素

继续判断栈顶元素是否和出栈序列中的第j个元素一致,直到到达入栈序列的末尾。

最后如果"stack"为空或指针j到达出栈序列的末尾就输出Yes,否则输出No

力扣735

小行星碰撞

思路:用栈模拟

以下情况不会发生碰撞,可把当前行星压入栈:

  1. 栈为空,不管当前行星是正是负(往左还是往右)都要压入栈
  2. 当前行星和栈顶行星同号说明同向移动不会碰撞;
  3. 当前行星往右移动,栈顶行星向左移动也不会碰撞

只有一种情况会发生碰撞,需要出栈当前行星往左,栈顶行星往右,做判断:

  1. 栈顶元素大于abs(当前元素),当前元素被撞毁;
  2. 栈顶元素等于abs(当前元素),栈顶弹出和当前元素抵消,
  3. 栈顶元素小于abs(当前元素),栈顶弹出,并与新栈顶继续完成上述判断

最终返回栈即可

单调栈概述

栈中的元素是严格单调递增 或者递减 的,也就是说:从底到栈顶,元素的值逐渐增大或者减小 。多用于求解元素的左右大小边界问题:

  1. 向左找第一个比自身大的数。
  2. 向左找第一个比自身小的数。
  3. 向右找第一个比自身大的数。
  4. 向右找第一个比自身小的数。

注意:对于给定的序列,第1,2点从序列的左边往右找;第3,4点从右往左找

操作(以底到顶递增为例):

  • 如果新的元素比栈顶元素大,就入栈
  • 如果新的元素比栈顶小,那就一直把栈内元素弹出来,直到栈顶比新元素小

元素间大小判断:(以底到顶递增为例):

  • 当栈中已有元素需要出栈时(遇见了比它小的新元素),说明后续这个新元素是需要出栈的元素向后找第一个比其小的元素
  • 当元素出栈后,新栈顶元素是出栈元素向前找第一个比其小的元素

题目

洛谷P5788

单调栈模板

思路:求每个数后第一个大于他的数。

底到顶 递减栈。

从后往前扫,对于每个元素:

  1. 弹出栈顶比它小的元素
  2. 此时栈顶就是答案(放到一个数组)
  3. 加入这个元素

输出答案数组。

力扣42

接雨水

思路:按行计算我们需要寻找一个元素的 右边最大元素以及左边最大元素,来计算雨水面积。

单调栈:底到顶 递减。

当枚举的将要入栈的元素大于栈顶时,说明出现了凹槽,计算该凹槽的蓄水量:例如:栈内元素:2,1,3要入栈,3比栈顶大,出现了凹槽。凹槽右边是将入栈的元素,左边是栈顶向下第一个大于栈顶的元素。

怎么计算蓄水量:

高*宽。宽是下标的差值高是下标对应的元素值,所以栈中存下标。所以:将要入栈的元素大于栈顶下标对应的元素时说明出现了凹槽。此时将栈顶记录下来之后,不断出栈,直到新的栈顶大于旧栈顶。记:新栈顶为ntop,旧栈顶为top,将入栈的下标为i,则:宽=i-top-1;高=min(h[ntop],h[i])-h[top]。

单调队列:

概念和单调栈类似。应用很少,多用于对一些算法的优化(动态规划等),除非去参加icpc,ccpc,不然基本接触不到,不再整述。

优先队列:

普通的队列是一种先进先出的数据结构,元素在队列尾追加,而从队列头删除。在优先队列中,元素被赋予优先级。当访问元素时,具有最高优先级的元素最先删除。优先队列具有最高级先出的特征。基于堆(大顶堆/小顶堆)实现。

编程中多使用C++容器:
#include <queue>
priority_queue<int>pq;//大顶堆
priority_queue<int,vector<int>,greater<int> > p;//小顶堆

相关推荐
寻寻觅觅☆12 小时前
东华OJ-基础题-106-大整数相加(C++)
开发语言·c++·算法
偷吃的耗子13 小时前
【CNN算法理解】:三、AlexNet 训练模块(附代码)
深度学习·算法·cnn
化学在逃硬闯CS13 小时前
Leetcode1382. 将二叉搜索树变平衡
数据结构·算法
ceclar12314 小时前
C++使用format
开发语言·c++·算法
Gofarlic_OMS14 小时前
科学计算领域MATLAB许可证管理工具对比推荐
运维·开发语言·算法·matlab·自动化
夏鹏今天学习了吗14 小时前
【LeetCode热题100(100/100)】数据流的中位数
算法·leetcode·职场和发展
忙什么果15 小时前
上位机、下位机、FPGA、算法放在哪层合适?
算法·fpga开发
董董灿是个攻城狮15 小时前
AI 视觉连载4:YUV 的图像表示
算法
ArturiaZ16 小时前
【day24】
c++·算法·图论
大江东去浪淘尽千古风流人物16 小时前
【SLAM】Hydra-Foundations 层次化空间感知:机器人如何像人类一样理解3D环境
深度学习·算法·3d·机器人·概率论·slam