顺序队列是一种基于数组实现的队列结构,其逻辑遵循“先进先出”(FIFO)原则

顺序队列是一种基于数组实现的队列结构,其逻辑遵循“先进先出”(FIFO)原则。它通过两个指针——队头指针 Q.front 和队尾指针 Q.rear 来标识当前队列的起始与结束位置。初始时,二者通常都指向数组起始位置(如0)。入队操作在 Q.rear 处插入元素,并将 Q.rear 后移;出队操作从 Q.front 取出元素,并将 Q.front 后移。

由于顺序队列使用固定大小的数组存储,随着入队和出队操作的进行,即使队列中存在空闲位置(前面已出队腾出的空间),当 Q.rear 到达数组末尾时也无法继续入队,造成“假溢出”。为解决这一问题,引入了循环队列的设计。

循环队列将数组视为首尾相连的环形结构,利用取余运算实现指针的循环移动:

  • 入队:Q.rear = (Q.rear + 1) % MAXSIZE
  • 出队:Q.front = (Q.front + 1) % MAXSIZE

此时,空队列和满队列都会出现 Q.front == Q.rear 的情况,因此需要特殊处理以区分两者。常见的方法是牺牲一个存储单元,规定当 (Q.rear + 1) % MAXSIZE == Q.front 时认为队列满,从而用该条件区分空与满状态。

这种结构广泛应用于操作系统中的任务调度、网络数据包缓冲、广度优先搜索(BFS)等需要按序处理的场景。

class CircularQueue:
    def __init__(self, k):
        self.maxsize = k + 1  # 实际分配k+1个空间,牺牲一个
        self.queue = [0] * self.maxsize
        self.front = 0
        self.rear = 0

    def is_empty(self):
        return self.front == self.rear

    def is_full(self):
        return (self.rear + 1) % self.maxsize == self.front

    def enqueue(self, value):
        if self.is_full():
            return False
        self.rear = (self.rear + 1) % self.maxsize
        self.queue[self.rear] = value
        return True

    def dequeue(self):
        if self.is_empty():
            return None
        self.front = (self.front + 1) % self.maxsize
        return self.queue[self.front]

判断循环队列为空或为满是实现循环队列的关键问题,因为队头指针 front 和队尾指针 rear 在空队列和某些情况下的满队列中可能具有相同的相对位置(即 front == rear),因此需要额外的机制来区分。

一、常见判定策略

1. 牺牲一个存储单元法(最常用)

这是教材和实际编码中最常用的策略:预留一个空位,规定队列满时 (rear + 1) % MAXSIZE == front

  • 空队列条件front == rear
  • 满队列条件(rear + 1) % MAXSIZE == front
  • 优点:逻辑清晰,判断简单,易于实现。
  • 缺点:浪费一个存储空间。
def is_empty(self):
    return self.front == self.rear

def is_full(self):
    return (self.rear + 1) % self.maxsize == self.front
2. 设置计数器 count 法

引入一个变量 count 记录当前队列中元素个数。

  • 空队列条件count == 0
  • 满队列条件count == MAXSIZE
  • 优点:充分利用所有空间,无需牺牲单元;判空判满更直观。
  • 缺点:需额外维护 count 变量,每次入队+1,出队-1。
def is_empty(self):
    return self.count == 0

def is_full(self):
    return self.count == self.maxsize
3. 增设标志位 tag 法

使用一个布尔标志 tag 标记最近操作是入队还是出队,辅助判断:

  • front == reartag == 0 → 表示刚进行了出队,队列为空;
  • front == reartag == 1 → 表示刚进行了入队,队列为满。
  • 优点:不浪费空间,仅用一个标志位。
  • 缺点:逻辑稍复杂,需在每次操作后更新 tag

示例:入队后若导致 rear == front,则置 tag = 1;出队后若导致 rear == front,则置 tag = 0

4. 使用长度独立数组索引(高级语言封装)

在 Python 等高级语言中,可通过封装动态管理逻辑长度,内部仍用列表模拟,但对外表现为循环队列行为,自动扩容或使用内置结构(如 collections.deque)。


二、总结对比

方法是否浪费空间判断难度额外开销适用场景
牺牲一个单元是(少用1个)简单教学、嵌入式、C语言实现
计数器 count简单一个整型变量实际工程常用
标志位 tag中等一个布尔变量资源受限系统
动态结构模拟简单较高内存高级语言应用

推荐做法

  • 学习阶段:推荐“牺牲一个单元”法,便于理解循环逻辑。
  • 工程实践:推荐“计数器法”,性能好且空间利用率高。
  • 在这里插入图片描述
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Bol5261

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值