栈和队列


栈和队列是操作受限的线性表。
为什么会出现栈和队列这种数据结构呢?栈和队列的全部操作都可以用不受限的线性表来实现,为什么会出现,我觉得可能是某些情况下线性表的功能太多了,恰好在没必要提供这么多的接口,于是就出现了栈和队列。

栈的定义

栈是限定在表尾进行插入或删除的线性表。表尾对应栈顶,表头对应栈底。

栈的特点

后入先出(LIFO)

栈的实现

栈的顺序实现

用一组地址连续的存储单元存放自栈底到栈顶的数据元素,设立栈顶指针top指向栈顶,栈底指针base指向栈底。在严蔚敏的《数据结构》中,栈顶指针top指向的是栈顶的下一个元素,初始化时,top=base;王道的数据结构单科书上面top指针指向的是栈顶元素,初始化时,top=-1。(在嵌入式中看到过四种不同的栈,严蔚敏的《数据结构》和王道的单科书上面的不是同一种。找到了:栈的四种方式)。

栈的链式实现

栈的链式实现和顺序实现差不多,区别就是使用链表来代替数组,Push和Pop都是在栈尾部进行。

栈的应用

数制转换、括号匹配、行编辑程序、迷宫问题还有函数调用。

栈的应用之函数调用(递归)

递归是栈的一种典型应用场景。递归即函数调用自身。先说下函数调用的步骤。

假设A函数调用B函数,那么A在调用B之前会做三件事

  1. 将所有的实参、返回地址等信息传给B保存
  2. 为B函数分配局部变量存储区
  3. 控制权转移到B函数

如果B函数执行完了,之后返回A函数步骤:

  1. 保存B运算结果
  2. 释放B的数据区
  3. 依照B保存的返回地址返回到A

从上面可以看到,A需要将实参、返回地址等信息传给B,这些信息用什么东西保存呢?栈。A调用B,这些信息入栈,如果B再调用C,那么再将B往C传的信息入栈,C结束之后,pop一次,得到的是B的返回地址,返回B函数,B结束之后再次pop,进入A函数。

递归中存在一个递归工作栈,就是用来存储函数切换之间的信息的,每一层递归对应了一层栈,每层栈都称为一个“工作记录”,栈顶的工作记录叫“活动记录”,还有一个当前环境指针指向“活动记录”。

那这个递归工作栈用不受限的线性表能实现吗?肯定可以的。但是用个栈刚刚好啊。

共享栈

利用栈底位置相对不变的特性,可以让两个顺序栈共享一个一维数组空间,从而节省空间。

假设100元素的数组当共享栈用,第一个栈的栈底就是0,第二个栈的栈底就是99。两个栈的栈顶就在0~99之间。

共享栈提出的原因就是为就是节省空间。

队列

上面栈的叙述是按照定义、结构、特点、实现、应用来进行的。同样的来看下队列。

队列的定义

队列是一种先进先出(FIFO)的线性表,只允许队尾插入,队头删除

特点

先进先出(FIFO)

队列的实现

和栈差不多,同样是两个指针,略了

队列的拓展

双端队列

双端队列是限定插入/删除操作在表的两端进行的线性表。也就是两端都可以插入和删除,但是不能从中间插入/删除。实际中可用输出受限或者输入受限的双端队列。

输出受限:可从两端插入,但是只能从一端删除。
输入受限:可从两端删除,只能从一段插入。

实际应用中双端队列不如栈和队列用的多。

循环队列

顾名思义,队列是循环的,这种队列一般是顺序存储的。为什么?

和栈一样,队列可以分为顺序存储和链式存储,但是队列和栈又不同。假设存在front指针指向队头,rear指针指向队尾,假设初始状态rear-front=n(即队列中又n个元素),那么删除是怎样的呢?front++;同理插入就是rear++。

假设有一个队列长度为100,初始状态front指向1的位置,rear指向10的位置,经过一段时间的操作之后,front指向95,rear指向100。这时候队列满了,实际上是没满的,因为0~95的位置都是空的,为了利用前面的空闲空间,出现了循环队列。

在链式存储中就不存在这种问题。在上面那种情况下,如果再有元素插入,那么是rear指向1,具体操作是:(rear+1)%MAXSIZE。

那循环队列什么时候满呢?

rear=front。同样队列空的时候也是这样。肯定不行,解决方案有两种,第一种设立一个标志位。第二种循环队列少存储一个元素。看看第二种。
第二种方式,队列满的时候就是(rear+1)%MAXSIZE=front了,空的时候就是rear=front。没问题。

另一个问题怎么求循环队列长度?

两种可能性;第一种rear>front,直接(rear-front)%MAXSIZE。为什么要%MAXSIZE,这种情况下不%MAXSIZE也是可以的。第二种情况rear<front,首先这种情况肯定存在的,如何求长度,(rear-front+MAXSIZE)%MAXSIZE;为什么要+MAXSIZE?这个想象一下跑圈就能理解了。

循环队列存在MAXSIZE,因此不能使用动态分配内存,即循环队列的大小一开始就是确定。

参考书目

严蔚敏《数据结构》
王道数据结构单科书

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值