1. 程式人生 > >【 C 】佇列 簡記

【 C 】佇列 簡記

瞭解佇列,不妨想象一下排隊,比如在食堂排隊打飯,先排上的人先接受服務,接受完服務之後退出(出隊),後來的人只有在隊尾插入佇列(入隊)。因此佇列有佇列頭和佇列尾,隊頭用於刪除元素操作,隊尾用來插入元素操作。

實現佇列的方式有很多種,靜態陣列,動態陣列和鏈式結構實現。

更官方一點這麼描述佇列:

佇列的長度以及佇列的元素型別等:

對佇列的操作主要有以下幾種:

佇列的順序儲存實現:

上圖定義了一個佇列的結構,包含的元素為一個數組,一個隊頭和隊尾的下標變數。

下面舉例說明佇列的順序儲存實現:

一開始的時候,佇列的Front 和 Rear 都初始化為 -1,表示佇列為空。

接下來,我們往佇列裡面加入一個工作,表示入隊:我們知道入隊是在隊尾實現的,所以Rear下標加1,變為0.

再加入一個工作,Rear繼續往後挪動:

接下來注意了,我們開始刪除一個工作,我們上面也說了刪除在隊頭刪除:此時Front為0.

下面繼續一系列這類的過程:總結起來就是當你入隊時,佇列的Rear加1,刪除一個元素(出隊),Front加1.

上圖中的這個狀態值得討論一番,此時,佇列尾部已經到頭(已經排到陣列的尾部),無法再加入,可是呢?佇列頭部又還有空間?怎麼辦呢?

解決這個問題的思路也很自然,後面排不下了,那就排到前面去嘛,下面引用順環佇列(也叫迴圈佇列):

如下圖,將上述陣列形成一個環:

我們約定,一開始Front和Rear相等並指向某一個位置,Front和Rear相等的時候,佇列為空:

接下來,我們加入元素:

刪除一個元素(出隊):

經過一系列操作,到達這個位置:

此時,我們如果再放一個元素:

那麼佇列的Front和Rear又指向了同一個位置,此時就存在一個問題了:

正如上圖所說,Front == Rear ,佇列是空還是滿?

無法甄別!

如下思考:

可知,如果佇列陣列大小為N,則Front和Rear差距有N種情況,我們就是要依靠這N種情況來判斷佇列的情況,而佇列裝載元素情況有N + 1種,所以用N種狀態來判別N + 1 種情況是不可能實現的。

必須另尋他路!

解決方案有三種:

1 是使用額外標記 Size,當你新增一個元素時,Size加1,刪除一個元素時,Size減1,這樣最後根據Size值是0還是佇列陣列的長度來判斷佇列是為空還是滿。

2 是使用額外標記 tag,當你新增一個元素時,tag為1,刪除一個元素時,tag為0,這樣可以根據最後tag為1還是0來判斷佇列是空還是滿。

3 是如果陣列空間為n,那麼我只使用n - 1個數組空間,這樣就不會出現佇列為空和滿,Front和Rear都是相等的尷尬情況了。這也是我們下面所要採取的方法。

實現佇列

判斷佇列滿的原理是:

以下圖這種情況為例:

執行下面這段程式碼,肯定成立,這是就說明佇列滿了!

像下面這種未滿的情況:

執行下面的程式碼:

可見,繼續在rear為4的這個陣列位置插入一個元素!

出佇列前,先判斷佇列是否為空。

如果不為空,則 front 加 1 這個位置的元素返回。

最後,提示下,上面所說的都是傳統的佇列實現方法。