佇列的順序儲存實現—迴圈佇列
阿新 • • 發佈:2019-01-01
佇列(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),但它還是存在順序儲存連結串列的不足之處:需要預先指定佇列的大小,這樣可能面臨著陣列可能溢位的問題。而佇列的鏈式儲存則不需要擔心佇列長度問題。