队列和栈都是线性数据结构,它们一个是先进先出,一个是先进后出,有着不同的使用场景。这两个数据结构基于链表,也可以用数组模拟这样的数据结构,通过 C++ 中 STL 提供的容器也可以更加方便快捷地实现。
队列
队列 (queue) 是在一端插入另一段删除的线性表,遵循先进先出,类似于排队,可以称为先进先出 (FIFO) 表。队列中,允许入队 (enqueue) 的一端为队尾,允许出队 (dequeue) 的一端为队头。以后的广度优先搜索就会用到它。
数组模拟队列
使用数组模拟队列需要一个存储数据的数组,同时用变量标记队头和队尾。
假设队列数组名为 q
,头指针为 ql
,尾指针为 qr
,则:
插入元素时,需要将队尾加上 1,假设元素为 x
。结果:q[++qr] = x;
;
删除元素时,需要将队头指向下一个元素,由于这不是链表,直接执行即可。结果:ql++;
;
访问队首,直接 q[ql];
;
访问队尾,直接 q[qr];
;
清空队列时,头指针尾指针初始化,ql = 1; qr = 0;
。
可见,数组模拟队列和数组模拟链表的缺点一样,内存不是动态分配的。这导致若数据过大则内存可能超出限制,若比数组的大小还大那就越界了,队列就溢出了。
队列的溢出
但由于数组是直接将队首队尾加来加去,可能会有队列(数组)前面还空着,但是队列溢出的情况这就叫做假溢出。若假溢出则需要使用循环队列,也就是说当尾指针超出数组,则将这一个元素从数组的开头放起。当然,若是真的全部存完了那有用的数据也会覆盖掉,这就是真溢出了。
STL queue
STL 提供的容器 queue
,需要引入 <queue>
头文件。通过模板,定义形式是这样:queue<[value type]> name
。
成员函数的使用:
front()
返回队首值。back()
返回队尾值。push([value])
元素入队。pop()
元素出队。empty()
返回布尔值,表示队列是否为空。size()
返回数值,表示队列里元素的数量。
容器不会假溢出,但是若队列为空还要 pop()
就会溢出。
栈
栈 (stack)是在同一端插入同一端弹出的表。元素可插入弹出的一段称为栈顶,另一端是栈底,遵循先进后出。
STL stack 容器需要引入 <stack>
头文件。成员函数有:top()
返回栈顶值push([value])
插入pop()
弹出empty()
是否为空栈size()
返回元素数量
同样的,容器没有上限,不会上溢出。但是若栈已空还要 pop()
就会造成下溢出。
附:visualgo 演示: