1. 程式人生 > >佇列的順序儲存實現—迴圈佇列

佇列的順序儲存實現—迴圈佇列

  佇列(queue)是一種只允許在一端插入元素,而在另一端刪除元素的線性表。它是一種先進先出(First In First Out,FIFO)的線性表。我們把允許插入的一端稱為隊尾,允許刪除元素的一端稱為隊頭。由於佇列也是一種線性表,所以佇列的實現也有順序儲存和鏈式儲存這兩種實現。當佇列順序儲存時,入佇列操作所需要的時間複雜度為O(1),而出佇列的時間複雜度為O(n)。因為刪除隊頭元素時,需要將後面的元素整體向前移動。為了避免順序儲存佇列刪除元素時,導致其他元素的移動,可以考慮迴圈佇列。迴圈佇列是指佇列的首尾兩個指標可以繞著佇列迴圈移動。例如,當往迴圈佇列中新增元素(入佇列)時,將佇列的尾指標rear向後移動一步,如果其超出了佇列的最大長度MAXSIZE則迴繞到佇列的頭部繼續;當從迴圈佇列中取元素(出佇列)時,將佇列的頭指標front向後移動一步,如果其超出了佇列的最大長度MAXSIZE則迴繞到佇列的頭部繼續。我們指定當佇列的頭指標front和尾指標rear重合時,即front == rear時,佇列為空。當rear與front相差一個位置時,我們就認定佇列已滿,即(rear+1)%MAXSIZE == front。對於佇列的長度計算,則是通過公式:length = (rear -front+MAXSIZE)%MAXSIZE。
    迴圈佇列涉及的主要操作有:初始化佇列、判斷一個佇列是否為空、返回佇列的長度、入佇列操作以及出佇列操作等。其程式碼實現如下:
#define MAXSIZE 20
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0

typedef int Status;

//迴圈佇列的順序儲存結構
typedef int ElemType;
typedef struct {
    ElemType data[MAXSIZE];//迴圈佇列大小
    int front;//佇列頭指標
    int rear;//佇列尾指標
}SqQueue;

/* *
 * 初始化一個佇列
 * 讓頭尾指標相同,從隊頭開始
 * */
Status InitQueue(SqQueue *Q){
   Q->rear = 0
; Q->front = 0; } /* * * 求迴圈佇列的長度 * 返回佇列的長度 * */ int QueueLength(SqQueue Q){ return ((Q.rear-Q.front + MAXSIZE)%MAXSIZE); } /* * * 迴圈佇列的入隊操作 * 成功返回1, * 失敗返回0 * */ Status EnQueue(SqQueue *Q,ElemType e){ if((Q->rear + 1)%MAXSIZE == Q->front) return ERROR;//迴圈佇列已滿 Q->data[Q->rear] = e; Q->rear = (Q->rear + 1
)%MAXSIZE;//隊尾指標指向下一個元素 return OK; } /* * * 迴圈佇列的出佇列操作 * 成功返回1,並把元素通過e返回 * 失敗返回0 * */ Status DeQueue(SqQueue *Q,ElemType *e){ if(Q->front == Q->rear) return ERROR;//迴圈佇列為空 *e = Q->data[Q->front]; Q->front = (Q->front + 1)%MAXSIZE;//隊頭指標指向下一個元素 return OK; } /* * * 判斷一個迴圈佇列是否為空 * 如果佇列為空,則返回TRUE,反之則返回FALSE * */ Status QueueEmpty(SqQueue Q){ return Q.rear == Q.front?TRUE:FALSE; }

測試程式碼為:

int main(){
    SqQueue Q;
    InitQueue(&Q);
    printf("The queue length is:%d\n",QueueLength(Q));
    if(QueueEmpty(Q))
        printf("The Queue is empty!\n");
    int i;
    for(i = 0; i < 10; i++){
       int  e = rand()%100 + 1;
       EnQueue(&Q,e);
       printf("The queue Length is:%d\n",QueueLength(Q));
    }
    int m;
    while(!QueueEmpty(Q)){
        if(DeQueue(&Q,&m))
            printf("delete the queue element is :%d\n",m);
        printf("The queue length is:%d\n",QueueLength(Q));
    }

    return 0;
}
迴圈佇列雖然可以做到插入和刪除元素所需要的時間複雜為為O(1),但它還是存在順序儲存連結串列的不足之處:需要預先指定佇列的大小,這樣可能面臨著陣列可能溢位的問題。而佇列的鏈式儲存則不需要擔心佇列長度問題。