Stack
Don't forget:
学习一个数据结构总是从三要素出发,当我们给出这个数据结构的逻辑结构并定义好它的基本运算时,我们就算是定义了这个数据结构(同时也定义了这样一个ADT),最后当我们确定了它的实现方式,即存储结构时,我们就实现了这个数据结构
定义
基本操作
小结
接下来讨论栈的存储结构的实现:
栈的逻辑结构为线性结构(逻辑上1对1),如果使用顺序结构实现栈,则称为顺序栈
顺序栈
基本操作
进栈
出栈
注意top在空栈时的初值为 0 还是 -1 ,对应的指针预取和数据读写顺序相反
顺序栈的缺点在于空间分配是静态的,有时为了提高空间利用率会使用 共享栈
小结
链栈
用链式存储实现的栈
对比前面学到的单链表,入栈和出栈其实就对应着从链表头插入和删除,当然,链栈也分为带头结点和不带头结点两种实现方式,代码与单链表的头插头删类似,自行练习
队列
与栈不同,队列是只允许尾进头出的线性表
队列的顺序存储结构代码实现
由于这里我们一开始设定的front和rear是指向同一个地址的,因此判空可以直接使用 if(Q.rear == Q.front)
但代价是判断队列满时不能再用上述语句,只能牺牲一个存储单元,用 if(Q.front=(Q.front+1)%MaxSize) 判断
即当队头等于队尾,队列空
当队尾的后面是队头,队满
但有的题会要求不允许牺牲这一个存储空间,这是由于队空队满的判断条件均为 Q.rear == Q.front,因此需要为判断构造复合条件
方法1:给队列添加一个int size属性记录当前队列中存放的数据个数,初值为零。
方法2:添加标签 tag 记录上一次操作为插入还是删除,显然只有插入可能导致队列满,也只有删除可能导致队列空:
同样,注意审题,不同的条件规定下对应的实现算法可能有很大不同,例如注意题目要求rear是指向队尾元素还是队尾的下一个元素,这决定了移动 rear指针 和 数据读写 的操作顺序以及队列的判空判满逻辑
小结
队列的链式存储结构
思路类似单链表,分为带头结点和不带头结点,注意尾插头出(先进先出FIFO),要点如下,代码略
建议和单链表对比学习
双端队列
双端队列在一定条件下可以退化成栈/队列
受限的双端队列
考点:根据不同的受限状况,判断某个输出序列是否合法