隊列是一種只容許在表的一端(稱爲隊尾)進行插入,而在另外一端(稱爲隊頭)進行刪除的線性表,是線性表的一種特例。node
順序隊列是用數組結構來表示的。爲了描述隊列的這種結構,咱們須要兩個代表隊頭和隊尾的指針,規定隊頭指針指向隊列頭結點的前一個位置,而隊尾指針指向隊列的尾結點。而爲何又會用到循環隊列呢,由於爲了防止「假上溢」對空間形成的浪費。「假上溢」是這麼來的,先說「上溢」和「下溢」。下溢就是當空對時,若是再作出隊操做,則會產生「下溢」。數組
當隊滿時,再作入對操做會產生「上溢」。可是,若是當前尾指針等於數組的上界,即便隊列不滿,再作入隊操做也會引發溢出。這種現象就是「假上溢」。然而有了循環隊列,咱們就能夠避免假上溢的問題了。可是循環隊列仍是有一個問題,就是判斷隊列與隊滿的狀況。若是按照前面的規定,隊頭指針指向隊列頭結點的前一個位置,而隊尾指針指向隊列的尾結點。那麼是分辨不出來隊滿與隊空的關係的。我看書中列出了3種解決此問題的方法。不過第三種最適合,它是採用少用一個節點空間,即頭指針指向的空間不使用。這樣的話。當front等於rear時,隊空;入隊後,當尾指針加1後等於頭指針,即:(rear+1)%maxsize = front.則說明這時隊列已滿。指針
下面是對循環順序隊列操做的一個總體代碼:code
#include <stdio.h> #include <stdlib.h> #define MAXSIZE 100 typedef 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"); else printf("入隊失敗!\n"); break; //出隊 case 3: ans = Sequeue_Out(q); if(ans) printf("出隊成功!\n"); else printf("出隊失敗!\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; else return 0; } //取得隊列頭結點 int Sequeue_GetFront(sequeue *q) { if(Sequeue_Empty(q)) //取頭結點先要判斷隊列是否爲空 { printf("隊列空!\n"); return 0; } else return 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"); }