三、队列的基本操作(接三十八)
1. 基本数据结构定义
复制代码
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define MAX_SIZE 100 // 队列最大容量
// 队列结构体定义
typedef struct {
int data[MAX_SIZE]; // 存储数据的数组
int front; // 队头指针
int rear; // 队尾指针
int size; // 当前队列大小
} Queue;
二、队列基本操作实现
1. 初始化队列
复制代码
// 初始化队列
void initQueue(Queue* q) {
q->front = 0; // 队头指针初始化为0
q->rear = -1; // 队尾指针初始化为-1(表示空队列)
q->size = 0; // 队列大小为0
}
2. 判断队列是否为空
复制代码
// 检查队列是否为空
bool isEmpty(Queue* q) {
// 方法1:使用size变量
return q->size == 0;
// 方法2:使用front和rear指针(循环队列)
// return (q->front == (q->rear + 1) % MAX_SIZE);
}
3. 判断队列是否已满
复制代码
// 检查队列是否已满
bool isFull(Queue* q) {
// 方法1:使用size变量
return q->size == MAX_SIZE;
// 方法2:使用front和rear指针(循环队列)
// return ((q->rear + 2) % MAX_SIZE == q->front);
}
4. 入队操作
复制代码
// 将元素添加到队列尾部
bool enqueue(Queue* q, int value) {
if (isFull(q)) {
printf("错误:队列已满,无法添加元素 %d\n", value);
return false; // 入队失败
}
// 移动rear指针(循环队列)
q->rear = (q->rear + 1) % MAX_SIZE;
// 在rear位置插入元素
q->data[q->rear] = value;
// 队列大小增加
q->size++;
printf("成功入队: %d (位置: %d)\n", value, q->rear);
return true; // 入队成功
}
5. 出队操作
复制代码
// 从队列头部移除元素
bool dequeue(Queue* q, int* value) {
if (isEmpty(q)) {
printf("错误:队列为空,无法移除元素\n");
return false; // 出队失败
}
// 获取队头元素
*value = q->data[q->front];
// 移动front指针(循环队列)
q->front = (q->front + 1) % MAX_SIZE;
// 队列大小减少
q->size--;
printf("成功出队: %d (新队头位置: %d)\n", *value, q->front);
return true; // 出队成功
}
6. 查看队头元素
复制代码
// 获取队头元素但不移除
bool peekFront(Queue* q, int* value) {
if (isEmpty(q)) {
printf("错误:队列为空,无队头元素\n");
return false;
}
*value = q->data[q->front];
printf("队头元素: %d\n", *value);
return true;
}
7. 查看队尾元素
复制代码
// 获取队尾元素但不移除
bool peekRear(Queue* q, int* value) {
if (isEmpty(q)) {
printf("错误:队列为空,无队尾元素\n");
return false;
}
*value = q->data[q->rear];
printf("队尾元素: %d\n", *value);
return true;
}
8. 获取队列大小
复制代码
// 返回队列中元素的数量
int getSize(Queue* q) {
return q->size;
// 如果不使用size变量,可以用以下公式计算:
// return (q->rear - q->front + MAX_SIZE) % MAX_SIZE + 1;
}
9. 清空队列
复制代码
// 清空队列中的所有元素
void clearQueue(Queue* q) {
q->front = 0;
q->rear = -1;
q->size = 0;
printf("队列已清空\n");
}
三、完整的队列操作示例
复制代码
// 打印队列内容
void printQueue(Queue* q) {
if (isEmpty(q)) {
printf("队列为空\n");
return;
}
printf("队列内容 (从队头到队尾): ");
if (q->front <= q->rear) {
// 正常情况:front <= rear
for (int i = q->front; i <= q->rear; i++) {
printf("%d ", q->data[i]);
}
} else {
// 循环情况:rear < front
for (int i = q->front; i < MAX_SIZE; i++) {
printf("%d ", q->data[i]);
}
for (int i = 0; i <= q->rear; i++) {
printf("%d ", q->data[i]);
}
}
printf("\n");
}
// 显示队列状态
void displayQueueStatus(Queue* q) {
printf("\n=== 队列状态 ===\n");
printf("队头位置: %d\n", q->front);
printf("队尾位置: %d\n", q->rear);
printf("队列大小: %d\n", getSize(q));
printf("队列容量: %d\n", MAX_SIZE);
printf("是否为空: %s\n", isEmpty(q) ? "是" : "否");
printf("是否已满: %s\n", isFull(q) ? "是" : "否");
printQueue(q);
}
// 主函数:测试队列基本操作
int main() {
Queue myQueue;
int value;
printf("=== 队列基本操作演示 ===\n");
// 1. 初始化队列
printf("\n1. 初始化队列\n");
initQueue(&myQueue);
displayQueueStatus(&myQueue);
// 2. 入队操作
printf("\n2. 入队操作演示\n");
printf("入队元素: 10, 20, 30, 40, 50\n");
enqueue(&myQueue, 10);
enqueue(&myQueue, 20);
enqueue(&myQueue, 30);
enqueue(&myQueue, 40);
enqueue(&myQueue, 50);
displayQueueStatus(&myQueue);
// 3. 查看队头和队尾
printf("\n3. 查看队头和队尾\n");
peekFront(&myQueue, &value);
peekRear(&myQueue, &value);
// 4. 出队操作
printf("\n4. 出队操作演示\n");
dequeue(&myQueue, &value);
printf("出队元素: %d\n", value);
dequeue(&myQueue, &value);
printf("出队元素: %d\n", value);
displayQueueStatus(&myQueue);
// 5. 获取队列大小
printf("\n5. 获取队列大小\n");
printf("当前队列大小: %d\n", getSize(&myQueue));
// 6. 继续入队
printf("\n6. 继续入队操作\n");
printf("入队元素: 60, 70, 80\n");
enqueue(&myQueue, 60);
enqueue(&myQueue, 70);
enqueue(&myQueue, 80);
displayQueueStatus(&myQueue);
// 7. 批量出队
printf("\n7. 批量出队直到队列为空\n");
while (!isEmpty(&myQueue)) {
dequeue(&myQueue, &value);
printf("出队: %d, 剩余大小: %d\n", value, getSize(&myQueue));
}
displayQueueStatus(&myQueue);
// 8. 测试边界情况
printf("\n8. 测试边界情况\n");
printf("从空队列出队: ");
dequeue(&myQueue, &value); // 应该失败
printf("查看空队列的队头: ");
peekFront(&myQueue, &value); // 应该失败
// 9. 清空队列
printf("\n9. 清空队列\n");
clearQueue(&myQueue);
displayQueueStatus(&myQueue);
return 0;
}
3. 操作的正式定义
| 操作 |
函数名 |
参数 |
返回值 |
说明 |
| 初始化 |
initQueue() |
Queue指针 |
void |
初始化队列 |
| 判空 |
isEmpty() |
Queue指针 |
bool |
检查队列是否为空 |
| 判满 |
isFull() |
Queue指针 |
bool |
检查队列是否已满 |
| 入队 |
enqueue() |
Queue指针, 元素值 |
bool |
元素添加到队尾 |
| 出队 |
dequeue() |
Queue指针, 接收指针 |
bool |
移除队头元素 |
| 查看队头 |
peekFront() |
Queue指针, 接收指针 |
bool |
获取队头元素 |
| 查看队尾 |
peekRear() |
Queue指针, 接收指针 |
bool |
获取队尾元素 |
| 获取大小 |
getSize() |
Queue指针 |
int |
返回元素数量 |
| 清空队列 |
clearQueue() |
Queue指针 |
void |
清空所有元素 |
四、状态转换图
复制代码
初始状态
↓
[空队列] (isEmpty = true)
↓ Enqueue(x)
[队列: x] (size = 1)
↓ Enqueue(y)
[队列: x ← y] (size = 2)
↓ Dequeue() → 返回x
[队列: y] (size = 1)
↓ Dequeue() → 返回y
[空队列] (isEmpty = true)
↓ Dequeue()
[错误/异常:队列为空]
五、关键特性总结
| 特性 |
描述 |
重要性 |
| 顺序性 |
元素保持严格的入队顺序 |
确保公平性 |
| 有限访问 |
只能访问队头和队尾 |
保证数据完整性 |
| 动态性 |
大小随操作变化 |
适应不同场景需求 |
| 效率 |
基本操作都是O(1) |
高性能实现基础 |
| 简洁性 |
接口简单明了 |
易于理解和实现 |