队列动画演示
一端进另一端出,配成环形数组就不用来回搬数据。
键盘:← → 单步 ·空格 播放/暂停 · R 重置 ·Home/End 到两端
队列把「先来后到」变成一条硬规矩:从 tail 进、从 head 出。如果用普通数组从头删起,每出队一次就要把剩下的整体前移一格,代价 O(n);把它弯成一个环,head 与 tail 只是两个下标,前进时各自加一再对容量取模,数据一格都不用搬。这一页反复做的就是绕回去的那一下:tail 走到数组末尾,下一个位置是 0。
环形数组最容易被忽略的细节是「留一格」。head 与 tail 重合就表示空队,那满了长什么样?如果允许 tail 追上 head,两者还是重合,程序就分不清队里是 0 个还是 cap 个。所以每次入队先算 (tail+1)%cap,撞上 head 就说明满了,代价是可用容量少一格。另一种写法是额外存一个 size 变量,把判断从「指针关系」搬到「计数」上。
队列演示怎么用
- 改容量:容量条控制环形数组有几格,可用元素是容量减一。起始 head 下标也能调,故意不从 0 开始,绕回的时机就会提前出现。
- 盯住两个指针:格子上的 head 与 tail 标签跟着走,重合时合并成一条标签。标签合并是因为一格只能挂一句标注,写两条会互相盖掉。
- 看两次失败:满队再入队与空队再出队各有一步专门停下来,note 里写清算式 (tail+1)%cap 与 head 的值,越界不会偷偷跳过。
- 核对 FIFO:下面那条纸带按出队次序记录每个元素,跑完直接和入队次序对照,顺序一致就说明绕回没打乱先来后到。
常见问题
为什么入队出队都是 O(1),链表的 head 删除不也是 O(1) 吗?
是的,链表版队列两端都是常数,但每个元素都要额外存一个指针,而且缓存友好性差。环形数组一次性开好格子,进出只改两个下标,工程里 BFS 与缓冲区更常用它。
判满一定要浪费一格?
用「留一格」的写法就必须浪费。另一种办法是维护 size,判满看 size 是否等于容量,一格都不浪费,代价是每次进出都要同时更新计数器,多线程下这个计数器还得起同步。
取模运算会不会拖慢速度?
容量取 2 的幂时,%cap 可以换成按位与 (cap-1),硬件上一个周期就完成。所以很多实现强制容量为 2 的幂,不只是好看。
演示编号 B02无需安装,手机端同样可用按 Ctrl + K 搜工具与演示