普通隊列尾部入隊、頭部出隊,數組尾部空間無法重用。循環隊列利用模運算讓 head、tail 繞回數組首部。關鍵在於:head == tail 既可能代表空,也可能代表滿。主流解法是犧牲一個存儲單元作為標誌:
head == tail(tail + 1) % MAX_SIZE == head實際可用容量 = MAX_SIZE - 1。
#define QUEUE_SIZE 10 static int queue[QUEUE_SIZE]; static int head = 0, tail = 0; // head 指向隊頭,tail 指向隊尾下一位置
EnQueuevoid EnQueue(int value) {
if ((tail + 1) % QUEUE_SIZE == head) {
printf("隊列已滿,無法入隊\n");
return;
}
queue[tail] = value;
tail = (tail + 1) % QUEUE_SIZE;
}
DeQueueint DeQueue() {
if (head == tail) {
printf("隊列為空,無法出隊\n");
return -1; // 約定錯誤碼
}
int temp = queue[head];
head = (head + 1) % QUEUE_SIZE;
return temp;
}
IsEmptyint IsEmpty() {
if (head == tail) { printf("隊列為空\n"); return 1; }
printf("隊列不為空\n"); return 0;
}
IsFullint IsFull() {
if ((tail + 1) % QUEUE_SIZE == head) { printf("隊列已滿\n"); return 1; }
printf("隊列未滿\n"); return 0;
}
PrintQueuevoid PrintQueue() {
for (int i = head; i != tail; i = (i + 1) % QUEUE_SIZE)
printf("%d ", queue[i]);
printf("\n");
}
#include <stdio.h>
#define QUEUE_SIZE 5 // 實際只能存 4 個元素
int queue[QUEUE_SIZE];
int head = 0, tail = 0;
void EnQueue(int value) { /* 同上 */ }
int DeQueue() { /* 同上 */ }
int IsEmpty() { /* 同上 */ }
int IsFull() { /* 同上 */ }
void PrintQueue() { /* 同上 */ }
int main() {
EnQueue(4); EnQueue(1); EnQueue(2); EnQueue(9); EnQueue(8); // 第 5 次會提示「已滿」
PrintQueue(); // 4 1 2 9
DeQueue(); DeQueue(); // 出 4, 1
PrintQueue(); // 2 9
return 0;
}
| 痛點 | 優化方案 | 代價 |
|---|---|---|
| 浪費 1 個槽位 | 額外 size 計數器 / tag 標誌位 | 額外內存/邏輯複雜度 |
| 固定容量 | 動態數組 + 2倍擴容 + 數據搬移 | 擴容時 O(n) 延遲 |
| 非線程安全 | 環形緩衝區 + 原子操作 / 鎖 | 同步開銷 |
PrintQueue 用 i < tail 而非模運算 → 跨越數組邊界時輸出錯誤。DeQueue 先移動 head 再取值 → 取到錯誤元素。完整代碼已上傳:Queue_Array。