一、 队列的基本概念
1. 什么是队列?
队列 (Queue) 是一种特殊的线性表,其操作受到限制:所有插入操作只能在表的一端进行,而所有删除操作则在另一端进行。
- 队尾 (Rear): 允许插入的一端。
- 队头 (Front): 允许删除的一端。
- 入队 (Enqueue): 插入新元素到队尾的操作。
- 出队 (Dequeue): 从队头删除元素的操作。
2. 核心特性:先进先出 (First-In, First-Out, FIFO)
队列的核心思想就像现实生活中的排队(例如食堂打饭),最早进入队列的元素将最先被移出。因此,队列也被称为“先进先出”表。
二、 队列的基本操作 (ADT)
一个完整的队列数据结构通常应支持以下基本操作:
EnQueue(item): 将元素item入队。DeQueue(): 队头元素出队。GetFront(): 获取队头元素的值(不出队)。IsEmpty(): 判断队列是否为空。IsFull(): 判断队列是否已满(主要用于顺序队列)。InitQueue(): 初始化队列。ClearQueue(): 清空队列。
三、 队列的实现方式
队列主要有两种实现方式:顺序存储(数组)和链式存储(链表)。
3.1 顺序队列 (Sequential Queue)
使用一段连续的存储空间(即数组)来实现队列。
1. 基础实现与“假溢出”问题
- 定义: 使用一个数组
data[MaxSize]和两个指针front和rear。front: 指向队头元素的下标。rear: 指向队尾元素下一个位置的下标。
- 初始状态:
front = 0,rear = 0。 - 队空判断:
front == rear。 - 入队操作:
data[rear] = item; rear++; - 出队操作:
item = data[front]; front++; - 问题: 随着不断地入队和出队,
front和rear指针会一直向后移动。当rear到达数组末尾 (rear == MaxSize) 后,即使数组前面因为出队操作已经有了空闲空间,也无法再插入新元素。这种现象称为 “假溢出” (False Overflow)。
如上图,虽然 0 到 front-1 的空间都空着,但因为 rear 已到末尾,系统会误判队列已满,无法再利用这些空间。
2. 循环队列 (Circular Queue) - 解决假溢出
为了解决“假溢出”,我们将数组在逻辑上视为一个环形空间。当指针移动到数组末尾时,它会“绕”回到数组的开头。
-
实现: 通过取模运算
%来实现环形逻辑。- 入队:
rear = (rear + 1) % MaxSize; - 出队:
front = (front + 1) % MaxSize;
- 入队:
-
队空队满的判断 (重点):
现在front == rear既可能是队空,也可能是队满。有两种主流的解决方法:-
方法一:使用计数器
countcount记录队列中元素的个数。- 队空:
count == 0。 - 队满:
count == MaxSize。
这是PPT中介绍的方法,逻辑清晰。
-
方法二:牺牲一个存储单元
- 规定队尾指针
rear的下一个位置是队头front时,队列为满。 - 队空:
front == rear。 - 队满:
(rear + 1) % MaxSize == front。
这种方法在不引入额外变量的情况下解决了问题,是教科书中更常见的方法。
- 规定队尾指针
-
【机试代码实现 - C++ & Python 循环队列】
以下是采用“牺牲一个存储单元”方法的实现,这在算法竞赛中更常用。
C++ 实现:
#include <iostream>
#include <vector>
class MyCircularQueue {
private:
std::vector<int> data;
int head;
int tail;
int capacity;
public:
MyCircularQueue(int k) {
capacity = k + 1; // 牺牲一个单元
data.resize(capacity);
head = 0;
tail = 0;
}
bool enQueue(int value) {
if (isFull()) {
return false;
}
data[tail] = value;
tail = (tail + 1) % capacity;
return true;
}
bool deQueue() {
if (isEmpty()) {
return false;
}
head = (head + 1) % capacity;
return true;
}
int Front() {
if (isEmpty()) {
return -1; // 或抛出异常
}
return data[head];
}
bool isEmpty() {
return head == tail;
}
bool isFull() {
return (tail + 1) % capacity == head;
}
};
Python 实现:
class MyCircularQueue:
def __init__(self, k: int):
self.capacity = k + 1 # 牺牲一个单元
self.data = [0] * self.capacity
self.head = 0
self.tail = 0
def enQueue(self, value: int) -> bool:
if self.isFull()

最低0.47元/天 解锁文章

被折叠的 条评论
为什么被折叠?



