隊列的順序存儲結構--循環隊列


1 定義
  隊列是只允許在一端進行插入操作,另一端進行刪除操作的線性表。
  隊列是一種先進先出(FIST IN FIRST OUT)的線性表,簡稱FIFO。允許插入的一端稱為隊尾,允許刪除的一端稱為對頭。

2 隊列的順序存儲結構
(1)隊列順序存儲的不足--引出循環隊列

    假設一個隊列有n個元素,則順序存儲的隊列需要建立一個大於n的數組,並把隊列的所有元素存儲在數組的前n個單元,數組下標為0的一端即為對頭。
    所謂的入隊,就是在隊尾追加一個元素,不需要移動任何元素,所以時間復雜度為O(1).
    隊列的出隊是在對頭,即下標為0的位置,也就意味着,隊列中的所有位置都得向前移動,以保證下標為0的位置,即對頭不為空。此時時間復雜度為O(n)。

    可是有時候想想,為什么出隊列時一定要全部移動呢?如果不限制隊列的元素一定要存儲在數組的前n個單元,出隊的性能就會大大增加。也就是說,隊頭不需要一定在下標為0的位置。

    為了避免當只有一個元素時,對頭和隊尾重合使得處理變得麻煩,所以引入兩個指針,front指針指向對頭元素,rear指針指向隊尾元素的下一個元素。這樣當front等於rear時,不是隊列中有一個元素,而是表示空隊列。

    假設數組的長度為5,空隊列及初始狀態如左圖所示,front與rear指針都指向下標為0的位置。當隊列中有4個元素時,front指針不變,rear指針指向下標為4的位置。

    此時出隊兩個元素,則front指針指向下標為2的位置,rear不變。再入隊一個元素,front指針不變,此時rear指針移動到數組之外。

    假設這個隊列中的總個數不超過5個,但目前如果接着入隊的話,會導致數組越界的錯誤,但是隊列在下標為0和1的位置是沒有元素的。我們把這種現象叫做“假溢出”。

    為了解決“假溢出”的問題,我們引入循環隊列。

(2)循環隊列

  為了解決“假溢出”的辦法,就是隊后面滿了,再從頭開始,也就是頭尾相接的循環。我們把隊列的這種投喂相接的順序存儲結構稱為循環隊列。

  繼續剛才的例子,將rear指針指向下標為0的位置,就不會導致rear指針指向不明的問題。

  接着入隊兩個元素,會發現rear指針與front重合了。

  此時問題又來了,剛才說了,當rear等於front時,表示是空隊列,現在當隊列滿時,rear也等於front。那么如何判斷隊列到底是空的還是滿的了?

  解決辦法為:當隊列空時,判斷條件就是rear=front, 當隊列滿時,我們修改其判斷條件,保留一個元素空閑。也就是說,隊列滿時,數組中還有一個空閑單元。以下兩種情況,我們都認為隊列已經滿了。

  由於rear可能比front大,也可能比front小,所以假設隊列的最大尺寸為QueueSize, 隊列滿的判斷條件改為(rear + 1)%QueueSize = front. 隊列的長度為(rear - front + QueueSize)% QueueSize.

 

循環隊列的順序存儲結構為

typedef int QElemType;
typedef struct {
    QElemType data[MAXSIZE];
    int rear;            //頭指針
    int front;           //尾指針,若隊列不為空,指向隊尾元素的下一個元素
}SqQueue;

循環隊列的初始化

//初始化一個空隊列
Status InitQueue(SqQueue *Q) {
    Q->rear = 0;
    Q->front = 0;
    return OK;
}

循環隊列求當前隊列的長度

//返回Q的元素個數,也就是隊列的當前長度
int QueueLength(SqQueue Q) {
    return (Q.rear - Q.front + MAXSIZE) % MAXSIZE;
}

循環隊列的入隊操作

//若隊列未滿,插入元素e為新的隊尾元素
Status insertQueue(SqQueue *Q, QElemType e) {
    if ((Q->rear + 1) % MAXSIZE == Q->front) {    //隊滿
        return ERROR;
    }
    Q->data[Q->rear] = e;
    Q->rear = (Q->rear + 1) % MAXSIZE;
    return OK;
}

循環隊列的出隊操作

//若隊列不為空,刪除Q的對頭元素,並用e返回
Status deleteQueue(SqQueue *Q, QElemType *e) {
    if (Q->rear == Q->front) {                //隊空
        return ERROR;
    }
    *e = Q->data[Q->front];
    Q->front = (Q->front + 1) % MAXSIZE
    return OK;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM