“Kahn 算法维护当前入度为零顶点的集合。取出一个顶点 $u$ 输出,并删除它的所有出弧;某个后继的剩余入度降至零时,将其放入队列或其他候选容器。循环不变量是:已输出前缀内部及其指向未输出区…”
形式陈述 ​
队列是抽象数据类型的一个具体接口:它只规定先进先出的可观察行为,不规定底层必须使用循环数组、链表还是持久化序列。
队列支持在尾部 enqueue(x)、在头部 dequeue(),满足先进先出:若依次入队
直觉
队列保留到达顺序,保持先进先出:最早进入且尚未删除、等待最久的对象最先被服务。这个顺序使它天然表示按发现时间扩张的前沿,而不是任意集合;队头与队尾职责分离,是它与栈的根本区别,也足以支持常数时间入队、出队。数组环形缓冲区通过模容量索引复用已释放位置,避免每次出队搬动剩余元素。
例子与边界
广度优先搜索用队列按距离层次展开顶点。环形缓冲区可在固定数组中复用头部空间,避免每次出队整体移动。优先队列按键而非到达时间删除,因此不是 FIFO 队列。
依次 enqueue
队列不支持直接删除中间元素而仍保持同一接口成本。并发队列还需定义原子性和内存回收,单线程指针操作不能直接推广为无锁正确性。
推论与应用
广度优先搜索、任务调度和消息缓冲依赖 FIFO 次序;双端队列把合法插入与删除扩展到两端,并可退化为队列或栈。顺序 RAM 中的环形数组可给最坏
外存优先队列按键选择元素并以块传输计费,既不保持到达顺序,也不能用内存队列的常数操作描述。蓄水池抽样只需顺序读一次未知长度数据流,却维护的是固定大小均匀样本,不是等待出队的全部元素。并发队列则还需规定线性化点、进展条件与内存可见性;这些结构共享“逐项到达”场景,但接口与保证各不相同。
参考资料
- Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, and Clifford Stein, Introduction to Algorithms, 4th ed., MIT Press, 2022, §10.1。
- Robert Sedgewick and Kevin Wayne, Algorithms, 4th ed., Addison-Wesley, 2011, §1.3。