You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

修改环形队列入队出队逻辑后,能否将F、R初始值设为0?

循环队列修改实现的可行性验证

在《计算机程序设计艺术》(TAOCP)第一卷2.2.2节“顺序分配”中,Donald Knuth提到循环队列的(4)(5)两种实现采用F=R=0的初始值,但使用(6a)(7a)时需设F=R=1,否则当F=0时无法检测溢出。我对(6a)(7a)进行了如下修改,请问是否仍可将F和R的初始值设为0?

func enqueue(X, Y) {
    if R == M {
        R = 0 // <- rewind to 0
    } else {
        R = R + 1
    }
    if R == F {
        return error("OVERFLOW")
    }
    X[R] = Y
}

func dequeue(X, &Y) {
    if F == R {
        return error("UNDERFLOW")
    }
    if F == M {
        F = 0  // rewind to 0
    } else {
        F = F + 1
    }
    Y = X[F]
}

补充说明:该实现仅在调用enqueue()和dequeue()时检测队列满(OVERFLOW)或空(UNDERFLOW),无需浪费第0个元素,无需让X[1]与X[M]逻辑相邻而跳过X[0]。另外,实现循环队列有预留一个元素的技巧:容量为M的队列仅能存M-1个元素,存M个元素需分配M+1空间,优点是无需调用入队出队即可判断空满:F=R为空,F=(R+1)mod M为满。Knuth此处未用该技巧,我认为若适当修改(6a)(7a),F=R=1和F=R=0无差异,特咨询该修改方案的可行性。


结论:该修改方案完全可行,初始值设为F=R=0是合理的

核心逻辑验证

这个实现通过调整指针移动与空满判断的时机,完美区分了空队列与满队列两种指针重合的场景,具体分析如下:

  1. 空队列状态:初始F=R=0时队列为空,dequeue()中先判断F==R,会直接触发UNDERFLOW,符合预期。当所有元素出队后,F最终会追上R,回到F=R的空状态。
  2. 入队与满队列判断:入队时先移动R指针(包含回绕到0的处理),再检查R==F——此时若重合,说明R移动后的位置恰好是F指向的队头前一个位置,意味着所有M个存储位置已被填满,触发OVERFLOW是正确的。队列最大容量为M,没有浪费任何空间。
  3. 出队逻辑:出队时先判断空状态,再移动F指针(同样包含回绕处理),然后取出对应位置的元素,确保只有队列非空时才会执行取数操作,逻辑严谨。

与Knuth原始实现的对比

你的修改本质上是将指针的起始偏移从1调整为0,循环逻辑完全自洽:

  • 无需跳过X[0]位置,充分利用了所有分配的存储空间;
  • 没有采用「预留一个元素」的技巧,但通过入队后判满、出队前判空的时机设计,同样准确区分了空/满状态,避免了指针重合带来的歧义。

边界场景验证

  • 首次入队:R从0变为1,R != F(0),成功存入X[1];
  • 存满M个元素:当R从M回绕到0时,此时F仍为0,触发OVERFLOW,说明已存满M个元素(X[1]到X[M]);
  • 全部出队:第M次出队后,F从M回绕到0,此时F=R=0,回到空状态,触发UNDERFLOW。

内容的提问来源于stack exchange,提问作者da_miao_zi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 15:34:54