stack/queue浅谈
前言
- stack和queue在STL之中一般不叫做容器, 它们都是以底层的容器来完成工作, stack/queue都是修改了底层容器的接口, 使其形成了另外一种表现形式, 一般把这样的称之为adapter
stack
- 众所周知, stack是一种后进先出的数据结构
- stack只有栈顶才可以push/pop元素
- stack无法进行遍历操作 ,stack也没有提供对应的迭代器
- stack的底层容器默认是deque, 也可以自己选择为其他的容器, 比方说list等具有双向开闭的容器
template <class T, class Sequence = deque<T>>
class stack {
protected:
Sequence c;// 底层的容器
};
- 借助于底层容器的实现, stack的操作均可以用底层容器来实现
push —— c.push_back()
pop —— c.pop_back()
- 总结: stack可以看成是封闭了front端的进出的deque adapter
queue
- 众所周知, queue是一种先进先出的数据结构
- queue是队头pop元素, 队尾push元素
- queue没有对应的迭代器, 也无法遍历操作
- queue的底层数据结构默认是deque, 也可以选择为其他的容器
template <class T, class Sequence = deque<T>>
class queue{
protected:
Sequence c; //底层的容器
};
- 借助于底层容器, queue的操作可以等价于:
push —— c.push_back()
pop —— c.pop_front()
- 总结: queue可以看成是封闭了front端的进, 封闭了back端的出的deque adapter
顺带一提deque
- deque的数据结构非常复杂, 我也只能从我所理解的角度来稍微解释一下deque容器
- deque是双向开口的连续线性空间, 这里的连续指的是逻辑上的连续, deque实际上是分段连续, 但对外显示出整体连续的假象
- deque并不会像vector那样“申请新空间-copy元素-释放原空间”, 但是用于主控的map字段是连续的一段空间——map并不是STL之中的map—— deque的map在容量不够的v时候会采用类似于vector扩容的方式扩容
- deque的map每一个节点都指向了一个连续的线性空间, 称之为缓冲区
- 在许多个分段连续的缓冲区之中对外表现出整体连续的现象是通过内部重载++, --, +=, -=
注:
以++为例
分为重载前++, 重载后++
如果已经到达所在缓冲区的最尾端, 就调用set_node函数将迭代器中字段node指向deque中的主控字段map的新的节点, 同时设置新的缓冲区的头和尾
- deque不仅仅维护着用于管理多个分段连续的线性空间的字段map, 主要的字段还有首尾迭代器分别指向第一个缓冲区的第一个元素和最后一个缓冲区的最后一个元素
注:
deque在空的时候即没有任何元素的时候也会持有一段缓冲区
- deque的相互关系如下: