Stack&Queue

Stack

Don't forget:

学习一个数据结构总是从三要素出发,当我们给出这个数据结构的逻辑结构并定义好它的基本运算时,我们就算是定义了这个数据结构(同时也定义了这样一个ADT),最后当我们确定了它的实现方式,即存储结构时,我们就实现了这个数据结构

image-20210410111820229

定义

image-20210410112248633

基本操作

image-20210410112717856

小结

image-20210410113106305

接下来讨论栈的存储结构的实现

栈的逻辑结构为线性结构(逻辑上1对1),如果使用顺序结构实现栈,则称为顺序栈

顺序栈

image-20210410115747242

基本操作

进栈

image-20210410120133387

出栈

image-20210410120500265

注意top在空栈时的初值为 0 还是 -1 ,对应的指针预取和数据读写顺序相反

顺序栈的缺点在于空间分配是静态的,有时为了提高空间利用率会使用 共享栈

image-20210410121206866

小结

image-20210410121506241

链栈

链式存储实现的栈

image-20210410121604328

对比前面学到的单链表,入栈和出栈其实就对应着从链表头插入和删除,当然,链栈也分为带头结点和不带头结点两种实现方式,代码与单链表的头插头删类似,自行练习

队列

与栈不同,队列是只允许尾进头出线性表

image-20210410122907444

image-20210410123222982

队列的顺序存储结构代码实现

由于这里我们一开始设定的front和rear是指向同一个地址的,因此判空可以直接使用 if(Q.rear == Q.front)

但代价是判断队列满时不能再用上述语句,只能牺牲一个存储单元,用 if(Q.front=(Q.front+1)%MaxSize) 判断

即当队头等于队尾,队列空

当队尾的后面是队头,队满

image-20210410125422232

但有的题会要求不允许牺牲这一个存储空间,这是由于队空队满的判断条件均为 Q.rear == Q.front,因此需要为判断构造复合条件

方法1:给队列添加一个int size属性记录当前队列中存放的数据个数,初值为零。

方法2:添加标签 tag 记录上一次操作为插入还是删除,显然只有插入可能导致队列满,也只有删除可能导致队列空:

image-20210410130816781

同样,注意审题,不同的条件规定下对应的实现算法可能有很大不同,例如注意题目要求rear是指向队尾元素还是队尾的下一个元素,这决定了移动 rear指针 和 数据读写 的操作顺序以及队列的判空判满逻辑

image-20210410131557765

小结

image-20210410131752961

队列的链式存储结构

思路类似单链表,分为带头结点和不带头结点,注意尾插头出(先进先出FIFO),要点如下,代码略

image-20210410133827930

建议和单链表对比学习

双端队列

双端队列在一定条件下可以退化成栈/队列

image-20210410134626106

受限的双端队列

image-20210410134741541

考点:根据不同的受限状况,判断某个输出序列是否合法

image-20210410140417793

原文地址:https://www.cnblogs.com/potofsalt/p/14640718.html