隊列(Queue)是只允許在一端進行插入操作,而在另一端進行刪除操作的線性表。是一種先進先出的線性表(FIFO)。 允許插入的一端稱為隊尾,允許刪除的一端稱為隊頭。我們在《棧的順序儲存結構》中發現,棧操作的top指標在Push時增 大而在Pop時減小,棧空間是可以重複利用的,而隊列的front、rear指標都在一直增大,雖然前面的元素已經出隊了,但它 所佔的儲存空間卻不能重複利用。但大多數程式並不是這樣使用隊列的,一般情況下出隊的元素就不再有儲存價值了,這些 元素的儲存空間應該回收利用,由此想到把隊列改造成環形隊列(Circular Queue):把queue數組想像成一個圈,front和 rear指標仍然是一直增大的,當指到數組末尾時就自動回到數組開頭,就像兩個人圍著操場賽跑,沿著它們跑的方向看,從 front到rear之間是隊列的有效元素,從rear到front之間是空的儲存位置,如果front追上rear就表示隊列空了,如果rear 追上front就表示隊列的儲存空間滿了。故一般我們將其實現為迴圈隊列,當出隊列時就不需要全部進行移動,只需要修改 隊頭指標,也可以解決“假溢出”的問題。
樣本程式:(改編自《大話資料結構》)
#include<iostream>using namespace std; #define MAXSIZE 20 typedef int ElemType; typedef struct{ ElemType data[MAXSIZE]; int front; /* 頭指標 */ int rear; /* 尾指標,若隊列不空,指向隊列尾元素的下一個位置 */} SqQueue; bool InitQueue(SqQueue *pq){ cout << "Init Queue ..." << endl; pq->front = 0; pq->rear = 0; return true;} bool ClearQueue(SqQueue *pq){ cout << "Clear Queue ..." << endl; pq->front = 0; pq->rear = 0; return true;} bool QueueEmpty(SqQueue Sq){ return (Sq.front == Sq.rear); /* 隊列空的標誌 */} int QueueLength(SqQueue Sq){ /* 隊列的當前長度 */ return (Sq.rear - Sq.front + MAXSIZE) % MAXSIZE;}/* 返回頭元素 */bool GetHead(SqQueue Sq, ElemType *pe){ if (QueueEmpty(Sq)) return false; else { *pe = Sq.data[Sq.front]; cout << "Get Head Item " << *pe << endl; return true; }} bool EnQueue(SqQueue *pq, ElemType Elem){ /* 隊列滿 */ if (QueueLength(*pq) == MAXSIZE) return false; cout << "EnQueue Item " << Elem << endl; pq->data[pq->rear] = Elem;/* 將元素賦值給隊尾 */ pq->rear = (pq->rear + 1) % MAXSIZE;/* rear指標向後移一位置, */ /* 若到最後則轉到數組頭部 */ return true;} bool DeQueue(SqQueue *pq, ElemType *pe){ if (QueueEmpty(*pq)) return false; *pe = pq->data[pq->front];/* 將隊頭元素賦值給*pe */ cout << "DeQueue Item " << *pe << endl; pq->front = (pq->front + 1) % MAXSIZE;/* front指標向後移一位置, */ /* 若到最後則轉到數組頭部 */ return true;} bool QueueTraverse(SqQueue Sq){ cout << "Queue Traverse ..." << endl; for (int i = 0; Sq.front + i < Sq.rear; i = (i + 1) % MAXSIZE) cout << Sq.data[i + Sq.front] << ' '; cout << endl; return true;} int main(void){ SqQueue Sq; InitQueue(&Sq); for (int i = 0; i < 5; i++) EnQueue(&Sq, i); QueueTraverse(Sq); int result; GetHead(Sq, &result); DeQueue(&Sq, &result); DeQueue(&Sq, &result); if (!QueueEmpty(Sq)) cout << "Queue Length: " << QueueLength(Sq) << endl; QueueTraverse(Sq); return 0;}
輸出為:
單是順序儲存,若不是迴圈隊列,演算法的時 間效能是不高的,但迴圈隊列也面臨著數組可能溢出的問題。