隊列是一種先進先出(FIFO)的線性表。對隊列的基本操做有兩種: 入隊(Enqueue),在表的末端(隊尾 tail)插入一個元素;出隊(Dequeue),刪除或返回在表的開頭(隊頭 head)的元素。本文介紹如何使用數組在 C 語言中實現一個隊列,平臺爲VS2010。算法
先建立一個隊列結構體,這個結構體應該包括這幾個元素:隊頭在數組中的位置(Front)、隊尾在數組中的位置(Rear)、隊列的大小(Size)、用於存儲隊列的數組(Array)以及數組的容量(Capacity):數組
typedef int ElementType; struct QueueRecord { int Capacity; // 數組容量 int Front; // 隊頭的位置 int Rear; // 隊尾的位置 int Size; // 隊列大小 ElementType *Array; // 用於存放隊列的數組 }; typedef struct QueueRecord Queue; typedef struct QueueRecord *PtrToQueue;
1、建立隊列數據結構
使用前面的結構體來建立一個隊列:ide
PtrToQueue CreateQueue(int capacity) { PtrToQueue queue = (PtrToQueue )malloc(sizeof(Queue)); if (queue == NULL) { perror("malloc failed!\n"); exit(EXIT_FAILURE); } queue->Capacity = capacity; queue->Array = (ElementType *)malloc(sizeof(ElementType) * capacity); MakeEmpty(queue); return queue; } void MakeEmpty(PtrToQueue Q) { Q->Size = 0; // 隊列長度設爲1 Q->Front = 1; // 隊頭位置爲 1 Q->Rear = 0; // 隊尾位置爲 0 }
2、入隊操做spa
向指定隊列的尾部插入一個元素,即爲入隊操做。在每次插入以前都要判斷隊列是否還有空間供新元素插入。code
void Enqueue(PtrToQueue Q,ElementType element) { if (IsFull(Q)) { perror("隊列已滿,入隊失敗\n"); exit(EXIT_FAILURE); } else { Q->Size++; // 隊列大小加 1 if (++Q->Rear == Q->Capacity) { Q->Rear = 0; } Q->Array[Q->Rear] = element; } } bool IsFull(PtrToQueue Q) { return Q->Size == Q->Capacity; }
在入隊操做中,設置了一個循環數組,在隊尾位置要超出數組邊界時,將隊尾放到數組開始處,以便最大利用數組空間。 blog
3、出隊操做隊列
將隊列的隊頭元素從隊列中刪除,對於數組隊列,只須要將隊頭位置加 1 便可。ci
void Dequeue(PtrToQueue Q) { if (IsEmpty(Q)) { perror("隊列爲空,沒法執行出隊操做\n"); exit(EXIT_FAILURE); } else { Q->Size--; // 隊列大小減 1 if (++Q->Front == Q->Capacity) { Q->Front = 0; } } } bool IsEmpty(PtrToQueue Q) { return Q->Size == 0; }
一樣的,爲了最大利用數組空間,出隊操做也使用了循環數組。 element
4、遍歷隊列
從隊頭元素開始遍歷整個隊列:
void TraverseQueue(PtrToQueue Q) { if (Q->Size == 0) { printf("隊列爲空\n"); } for (int i = 0; i < Q->Size; i++) { if (Q->Front + i < Q->Capacity) { printf("%d ", Q->Array[Q->Front + i]); } else { printf("%d ", Q->Array[Q->Front + i - Q->Capacity]); } } }
5、完整代碼
#include <stdio.h> #include <stdlib.h> typedef int ElementType; struct QueueRecord { int Capacity; // 數組容量 int Front; // 隊頭的位置 int Rear; // 隊尾的位置 int Size; // 隊列大小 ElementType *Array; // 用於存放隊列的數組 }; typedef struct QueueRecord Queue; typedef struct QueueRecord *PtrToQueue; PtrToQueue CreateQueue(int capacity); void MakeEmpty(PtrToQueue Q); void Enqueue(PtrToQueue Q, ElementType element); void Dequeue(PtrToQueue Q); bool IsFull(PtrToQueue Q); bool IsEmpty(PtrToQueue Q); void TraverseQueue(PtrToQueue Q); ElementType Peek(PtrToQueue Q); int main() { PtrToQueue newQueue = CreateQueue(10); // 建立一個空隊列 for (int i = 0; i < 10; i++) { Enqueue(newQueue,i); // 向隊列中添加元素 } TraverseQueue(newQueue); // 遍歷隊列 Dequeue(newQueue); // 出隊 Dequeue(newQueue); // 出隊 TraverseQueue(newQueue); Enqueue(newQueue, 50); // 入隊 TraverseQueue(newQueue); return 0; } // 建立一個隊列 PtrToQueue CreateQueue(int capacity) { PtrToQueue queue = (PtrToQueue )malloc(sizeof(Queue)); if (queue == NULL) { perror("malloc failed!\n"); exit(EXIT_FAILURE); } queue->Capacity = capacity; queue->Array = (ElementType *)malloc(sizeof(ElementType) * capacity); MakeEmpty(queue); return queue; } void MakeEmpty(PtrToQueue Q) { Q->Size = 0; Q->Front = 1; Q->Rear = 0; } // 入隊 void Enqueue(PtrToQueue Q,ElementType element) { if (IsFull(Q)) { perror("隊列已滿,入隊失敗\n"); exit(EXIT_FAILURE); } else { Q->Size++; if (++Q->Rear == Q->Capacity) { Q->Rear = 0; } Q->Array[Q->Rear] = element; } } // 出隊 void Dequeue(PtrToQueue Q) { if (IsEmpty(Q)) { perror("隊列爲空,沒法執行出隊操做\n"); exit(EXIT_FAILURE); } else { Q->Size--; if (++Q->Front == Q->Capacity) { Q->Front = 0; } } } // 判斷隊列是否爲滿 bool IsFull(PtrToQueue Q) { return Q->Size == Q->Capacity; } // 判斷隊列是否爲空 bool IsEmpty(PtrToQueue Q) { return Q->Size == 0; } // 遍歷隊列 void TraverseQueue(PtrToQueue Q) { if (Q->Size == 0) { printf("隊列爲空\n"); } for (int i = 0; i < Q->Size; i++) { if (Q->Front + i < Q->Capacity) { printf("%d ", Q->Array[Q->Front + i]); } else { printf("%d ", Q->Array[Q->Front + i - Q->Capacity]); } } printf("\n"); } // 獲取隊頭元素 ElementType Peek(PtrToQueue Q) { return Q->Array[Q->Front]; }
這段代碼建立了一個隊列,將整數 0~9分別入隊,而後執行兩次出隊操做,再將整數 50 入隊,程序執行結果以下:
參考資料:
《數據結構與算法分析 -- C語言描述》