一、循环队列判断队满有什么问题?
循环队列用数组实现,会遇到一个问题:
-
队空 :
front == rear -
队满 :
front == rear
两个状态完全一样,无法区分。
二、三种解决办法
方法1:牺牲一个元素空间(最常用)
-
思路:刻意少用一个数组位置,不存数据,专门用来区分空满
-
队空:
front == rear -
队满:
(rear + 1) % MAXSIZE == front -
最大容量:
MAXSIZE - 1 -
优点:简单直观,无需额外变量
-
缺点:浪费 1 个单元空间
cpp
#include <stdio.h>
#define MAXSIZE 5 // 数组长度5,牺牲1个,最多存4个元素
// 循环队列结构
typedef struct {
int data[MAXSIZE];
int front; // 队头指针
int rear; // 队尾指针
} SqQueue;
// 初始化
void InitQueue(SqQueue *Q) {
Q->front = Q->rear = 0;
}
// 判空
int QueueEmpty(SqQueue Q) {
return Q.front == Q.rear;
}
// 判满(核心:牺牲1个元素)
int QueueFull(SqQueue Q) {
return (Q.rear + 1) % MAXSIZE == Q.front;
}
// 入队
int EnQueue(SqQueue *Q, int e) {
if (QueueFull(*Q)) {
printf("队列已满!\n");
return 0;
}
Q->data[Q->rear] = e;
Q->rear = (Q->rear + 1) % MAXSIZE;
return 1;
}
// 出队
int DeQueue(SqQueue *Q, int *e) {
if (QueueEmpty(*Q)) {
printf("队列已空!\n");
return 0;
}
*e = Q->data[Q->front];
Q->front = (Q->front + 1) % MAXSIZE;
return 1;
}
// 测试
int main() {
SqQueue Q;
InitQueue(&Q);
// 入队 4 个(满)
EnQueue(&Q, 10);
EnQueue(&Q, 20);
EnQueue(&Q, 30);
EnQueue(&Q, 40);
EnQueue(&Q, 50); // 失败:队列已满
// 出队
int e;
while (!QueueEmpty(Q)) {
DeQueue(&Q, &e);
printf("出队:%d\n", e);
}
return 0;
}
方法2:增设标志位 flag
-
思路:增加一个变量
flag,标记最近一次是入队还是出队 -
队空:
front == rear && flag == 0 -
队满:
front == rear && flag == 1 -
flag 规则:
-
入队成功:
flag = 1 -
出队成功:
flag = 0
-
-
优点:不浪费空间,可存满 MAXSIZE 个元素
-
缺点:多一个变量,逻辑稍复杂
方法3:增设计数器 count
-
思路:用一个变量
count记录队列中实际元素个数 -
队空:
count == 0 -
队满:
count == MAXSIZE -
入队:
count++,出队:count-- -
优点:直观,可存满 MAXSIZE 个元素,判空判满最清晰
-
缺点:需要维护计数变量