【 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 這個位置的元素返回。
最後,提示下,上面所說的都是傳統的佇列實現方法。