数据结构(九)—— 栈(Stack)小结

栈:可能是应用频率最高的数据结构之一(另外一个是队列),是线性表的限制版。把线性表的插入和删除操作限制在同一端进行,就得到栈数据结构。

由于是线性表的限制版,栈的所有操作在线性表上都可以进行,那为什么还要专门设计栈这一种数据结构呢

我的理解是公式化描述和链式描述已经从最根本上定义了线性表,栈可以直接从线性表类派生出,但会牺牲一些执行效率。栈的存在是线性表的应用的需要,为不同的需求制订出最匹配的解决方案,永远也用不到的一些部分则不需要为用户提供,即“奥卡姆剃刀原理”。

所以栈以及马上要来的队列这一部分,都有两个重点。

  • 逻辑结构、存储结构和对数据的运算结构,明确概念
  • 应用领域,应用实例和应用总结

逻辑结构:线性结构
存储结构:数组描述或链表描述
对数据的运算:empty()、size()、top()、pop()、push(x)

概念:可以联想任何摞在一起的东西,往上添加或者拿去都必须在顶端进行,不可以“釜底抽薪”。

应用实例:

  • 括号匹配问题
  • 汉诺塔问题
  • 列车车厢重排
  • 离线等价类
  • 等等

括号匹配是最简单的栈应用,只需要用到一个栈。类似的问题还有判断字符串是否中心对称。关键是找到题目中的对称或局部对称条件,元素依次入栈再出栈(中间不允许出栈),正好完成一次翻转,入栈顺序和出栈顺序对称。

汉诺塔问题是利用递归求解,这里使用栈是为了保存每一步的三座塔的布局,以便可以直观的观察到,算法仍然是递归。选用栈是因为汉诺塔的对盘子的操作正是只能从顶部操作(正好是摞在一起的盘子)。

列车车厢重排问题
有n个车厢,车厢编号为1-n,给定任意编号次序的车厢,经过k个转轨站,要求将车厢驶入或不驶入转轨站,每个转轨站可驶入的车厢数不限,要求出轨之后车厢编号为n,n-1,n-2,…,1

我尝试总结n和k之间的关系,即给定n,可以重排成功的k最小值。
发现n和k之间没有特定的关系,决定k的最小值的是车厢的顺序。
比如有9个车厢:

  • 987654321 ——> 987654321 需要0个转轨站
  • 123456789 ——> 987654321 需要1个转轨站
  • 198765432 ——> 987654321 需要8个转轨站
  • 581742963 ——> 987654321 需要3个转轨站
  • 185742963 ——> 987654321 需要4个转轨站

如果有9个车厢,那么排列组合数就有9!个,也没有找到可以概括车厢顺序和k的关系的公式(枯了)。
也就是说根据车厢顺序不同,只要k<n-1,就有可能重排失败

至于火车重排为什么用到了栈,因为作为缓冲通道的转轨站只有一个出口呀,如果将转轨站和出轨道连通的话,同样可以用队列来解。
在这里插入图片描述
最后回顾一下火车重排的算法思想吧

算法思想:

  1. 任何一条转轨站的车厢从顶到底必须是递增排序,否则一定排序失败
  2. 重排时首先检验应排车厢编号,当入轨的车厢编号或转轨站顶部的车厢编号有应排车厢编号时,车厢出站,排序。
  3. 若第二条的车厢不存在,入轨的车厢进入转轨站
  4. 选择转轨站时,编号为u的车厢应该进入的转轨站顶部车厢应是车厢编号大于u的最小者
  5. 若第四条的转轨站不存在,进入空转轨站
  6. 若第五条的转轨站不存在,排序失败
  7. 当最后的入轨车厢出轨后,排序完成

离线等价类:

离线等价类问题首先要清楚等价类的概念
问题描述:输入为元素数目n,关系对数目r以及r个关系对,目标是把n个元素划分为等价类

不管是从课本还是网上我都没有找到为什么离线等价类一定要用栈,书上也只是简单提了一句性能优于公式化线性表。
我认为用队列也完全ok。

因为算法中需要的是一个不规则的二维数组,并且只要求可以方便的添加和删除元素,任何操作都不需要指定位置。最符合要求的便为栈和队列。

猜你喜欢

转载自blog.csdn.net/qq_41882686/article/details/106979115