隊列是一種只允許在表的一端(稱為隊尾)進行插入,而在另一端(稱為隊頭)進行刪除的線性表,是線性表的一種特例。
順序隊列是用數組結構來表示的。為了描述隊列的這種結構,我們需要兩個表明隊頭和隊尾的指標,規定隊頭指標指向隊列頭結點的前一個位置,而隊尾指標指向隊列的尾結點。而為什麼又會用到迴圈隊列呢,因為為了防止“假上溢”對空間造成的浪費。“假上溢”是這麼來的,先說“上溢”和“下溢”。下溢就是當空對時,如果再做出隊操作,則會產生“下溢”。
當隊滿時,再做入對操作會產生“上溢”。但是,如果當前尾指標等於數組的上界,即使隊列不滿,再做入隊操作也會引起溢出。這種現象就是“假上溢”。然而有了迴圈隊列,我們就可以避免假上溢的問題了。但是迴圈隊列還是有一個問題,就是判斷隊列與隊滿的情況。如果按照前面的規定,隊頭指標指向隊列頭結點的前一個位置,而隊尾指標指向隊列的尾結點。那麼是分辨不出來隊滿與隊空的關係的。我看書中列出了3種解決此問題的方法。不過第三種最適合,它是採用少用一個節點空間,即頭指標指向的空間不使用。這樣的話。當front等於rear時,隊空;入隊後,當尾指標加1後等於頭指標,即:(rear+1)%maxsize
= front.則說明這時隊列已滿。
下面是對迴圈順序隊列操作的一個整體代碼:
#include <stdio.h>#include <stdlib.h>#define MAXSIZE 100typedef struct node{int data[MAXSIZE];int front;//存放隊列頭地址int rear;//存放隊列尾地址}sequeue;void Sequeue_SetNull(sequeue *q);//隊列置空int Sequeue_Empty(sequeue *q);//判斷隊列是否為空白int Sequeue_GetFront(sequeue *q);//得到隊列頭結點int Sequeue_In(sequeue *q, int dat);//入對操作int Sequeue_Out(sequeue *q);//出隊操作void ShowSequeue(sequeue *q);//輸出顯示隊列int main(void){int num, i, dat, choice, ans;sequeue *q;q = (sequeue*)malloc(sizeof(sequeue));printf("迴圈順序隊列的操作練習:\n");printf("輸入你想建立隊列的資料個數:\n");scanf("%d", &num);if(num>MAXSIZE-1){printf("隊列結點數大於最大允許空間!\n");return 0;}Sequeue_SetNull(q);printf("請依次輸入隊列資料:\n");for(i=1; i<num+1; i++)//迴圈輸入隊列結點資料{scanf("%d", &dat);q->data[i] = dat;q->rear = i;}while(1){printf("隊列操作:\n");printf("1.取隊列結點\n");printf("2.入隊操作\n");printf("3.出隊操作\n");printf("4.輸出隊列\n");printf("5.退出程式\n");printf("做出選擇:\n");scanf("%d", &choice);switch(choice){//取隊列頭結點case 1:dat = Sequeue_GetFront(q);printf("頭結點為:%d\n", dat);break;//入隊case 2:printf("輸入你想入隊的資料:\n");scanf("%d", &dat);ans = Sequeue_In(q, dat);if(ans)printf("入隊成功!\n");elseprintf("入隊失敗!\n");break;//出隊case 3:ans = Sequeue_Out(q);if(ans)printf("出隊成功!\n");elseprintf("出隊失敗!\n");break;//輸出顯示隊列case 4:ShowSequeue(q);break;//退出程式case 5:return 0;break;default:printf("選擇無效!\n");break;}}}//隊列置空void Sequeue_SetNull(sequeue *q){q->rear = 0;//其中數組第一個節點空間不使用(即下標為0數組元素),用作隊列滿與空的區別q->front = 0;}//判斷隊列是否為空白int Sequeue_Empty(sequeue *q){if(q->front == q->rear)//頭結點等於尾結點即表示隊列為空白return 1;elsereturn 0;}//取得隊列頭結點int Sequeue_GetFront(sequeue *q){if(Sequeue_Empty(q))//取頭結點先要判斷隊列是否為空白{printf("隊列空!\n");return 0;}elsereturn q->data[(q->front+1) % MAXSIZE];}//入隊int Sequeue_In(sequeue *q, int dat){if((q->rear+1)%MAXSIZE == q->front)//入隊先要判斷隊列是否已經滿了return 0;else{q->rear = (q->rear+1) % MAXSIZE;//使用求模運算q->data[q->rear]= dat;return 1;}}//出隊int Sequeue_Out(sequeue *q){if(Sequeue_Empty(q))//出隊先要判斷隊列是否為空白return 0;else{q->front = (q->front+1) % MAXSIZE;//求模運算return q->data[q->front];}}//輸出顯示隊列void ShowSequeue(sequeue *q){int i;i = q->front+1;while(i != q->rear+1){printf("%d ", q->data[i]);i++;}printf("\n");}