c++中如何实现顺序循环队列_c++循环队列入队出队操作

取模运算使rear和front在数组末尾后回到开头,实现逻辑环形;队空判front==rear,队满判(rear+1)%capacity==front;rearElement需(rear-1+capacity)%capacity防负。

为什么 frontrear 要用取模运算

顺序循环队列本质是用一维数组模拟环形结构,物理上数组是线性的,但逻辑上要让 rear 到末尾后回到开头。不用 % size 就会越界——比如数组长度为 5,当前 rear == 4,入队后应变成 0,而不是 5。所有移动操作(rear = (rear + 1) % capacityfront = (front + 1) % capacity)都依赖这个取模,否则就不是“循环”。

如何判断队空和队满(最容易错的两个条件)

顺序循环队列无法靠 front == rear 同时表示空和满,必须牺牲一个存储位置或引入额外变量。主流做法是「牺牲一个位置」:用 (rear + 1) % capacity == front 判满,用 front == rear 判空。这意味着容量为 n 的数组最多存 n-1 个元素。若强行塞满 n 个,frontrear 将再次相等,与队空冲突,导致逻辑崩溃。

  • 判空:front == rear
  • 判满:(rear + 1) % capacity == front
  • 入队前必须先判满,出队前必须先判空
  • 初始化时 front = rear = 0,此时队空

enqueuedequeue 的标准写法(带边界检查)

这两个操作看似简单,但漏掉判空/判满、忘记更新索引、搞反取模对象,都会引发未定义行为。尤其注意:入队是先赋值再动 rear,出队是先取值再动 front;且所有索引更新必须立即取模,不能等到最后算。

class CircularQueue {
private:
    int* data;
    int capacity;
    int front;
    int rear;

public: CircularQueue(int k) : capacity(k + 1), front(0), rear(0) { data = new int[capacity]; }

bool enqueue(int value) {
    if ((rear + 1) % capacity == front) return false; // 队满
    data[rear] = value;
    rear = (rear + 1) % capacity;
    return true;
}

bool dequeue() {
    if (front == rear) return false; // 队空
    front = (front + 1) % capacity;
    return true;
}

int frontElement() {
    if (front == rear) throw std::runtime_error("Queue is empty");
    return data[front];
}

int rearElement() 

{ if (front == rear) throw std::runtime_error("Queue is empty"); return data[(rear - 1 + capacity) % capacity]; }

};

为什么 rearElement() 要写成 (rear - 1 + capacity) % capacity

直接写 (rear - 1) % capacityrear == 0 时会得到负数(如 -1),C++ 中负数取模结果仍为负(-1 % 5 == -1),而非预期的 4。加一个 capacity 再取模可强制转正:(0 - 1 + 5) % 5 == 4。这是循环队列里访问“逻辑上 rear 前一个位置”的安全写法,任何涉及减法后取模的地方都要防负。

实际使用中,只要索引计算含减法,就该默认套一层 + capacity 再取模。这不是过度防御,是 C++ 取模语义决定的硬约束。