三、隊空與隊滿的判斷
總結在演算法中,佇列是個常用的資料型別,具有先進先出的儲存特點。
在python中我們直接呼叫 collections.deque() 就可以構建乙個佇列,那麼在c語言中,該如何簡單地實現乙個佇列呢?
為了節省記憶體空間,c中的佇列要用迴圈佇列實現,它可以迴圈使用位置存放資料。以此實現新入隊的資料,直接覆蓋前面已出隊的無用資料。而不需要考慮如何刪除已出隊的元素,並且使得佇列的長度可以是有限的,只要滿足同時要存放的最多元素個數即可。
迴圈佇列視覺化的圖如下:
先不管這個圈,我們把它拉直的話就是乙個陣列,下標從0開始。它有乙個最大長度的設定,記為max
size
maxsize
maxsiz
e,在初始化時要定義好。在上圖中,max
size
=8maxsize=8
maxsiz
e=8。
但要注意,在我們使用時,這個佇列能同時存放的最大元素個數是 max
size
−1=7
maxsize-1=7
maxsiz
e−1=
7。這是為了能有效判斷隊滿還是隊空,在下面會講到。
除了陣列,我們還設有兩個指標:隊頭指標(front)用於指示隊首元素的位置,隊尾指標(rear)用於指示佇列最後乙個元素的位置。
初始化過程中,就是定義乙個陣列,和兩個指標。當然這個指標不真就是c語言中的指標 ∗
*∗ 資料型別,而是說可以代表陣列中元素位置的「東西」。那麼最簡單的辦法,front 和 rear 直接是陣列下標最好。
我們初始化乙個存放元素是整數的佇列deq
uedeque
dequ
e,並且希望它最多能同時存放max
lenmaxlen
maxlen
個資料:
int deque[maxlen+1]
;//注意初始化時,陣列長度要在資料長度基礎上加1
int front=
0, rear=
0;
注意陣列長度是max
len+
1maxlen+1
maxlen
+1。當想將乙個元素加入佇列時,我們知道要加在隊尾,此時隊尾指標rear指向的陣列位置就是可以新增新元素的位置。因此直接將新元素賦給rear指向的位置,再將rear後移一位。
為了防止rear的值超出陣列長度,我們在後移rear後,對陣列長度取個餘,讓rear迴圈地指回陣列前面的位置。不過,如果我們能很好地設定陣列的長度,保證能一次性放下所有元素,這一步就不是必要的,
int in=5;
//要入隊的元素
deque[rear]
= in;
rear ++
;// 或者:
// deque[rear++] = in;
rear = rear%
(maxlen+1)
;
出隊時從隊首彈出第乙個元素,front指標指向的恰好就是佇列的第乙個元素。因此直接獲取front指向的元素,並將front後移一位。後移front是因為當前值在主觀上已經被彈出,雖然它客觀上還在這個陣列中,但已經可以看作不存在於陣列中了;後面的乙個值才是真正的隊首元素,需要將front指向它。
同樣,對後移後的front取餘。
突然感覺有點哲學意味,嘖…
int out;
//表示彈出的元素
out = deque[front]
;front ++
;// 或者:
// out = deque[front++];
front = front%
(maxlen+1)
;
可以看出rear指標指向隊尾,但它指向的位置永遠是還沒有儲存新元素的(因為我們插入新元素後,馬上將rear後移了);front指向隊首元素,指向的位置是有元素的。
所以,佇列中有效元素的個數(即佇列長度)是
而不是rea
r−fr
ont+
1rear-front+1
rear−f
ront
+1直觀理解,當佇列長度為0時,隊空。因此rea
r==f
ront
rear==front
rear==
fron
t就是隊空條件。
還記得嗎~在定義佇列陣列時,我們給陣列長度刻意多加了個1,這是為了留出來乙個多餘的位置不放元素。這樣,我們才能區分隊滿和隊空的狀態。
隊滿時,rear和front的位置關係是這個亞子的:
直觀來看,轉圈圈方向上,rear在front前乙個位置的時候,佇列就滿了。從數學上嚴謹推導一下,
即( re
ar+1
)%(m
axle
n+1)
==fr
ont(rear+1)\%(maxlen+1)==front
(rear+
1)%(
maxl
en+1
)==f
ront
時,隊滿。
這時,我們思考一下為什麼不能讓元素把陣列全占滿?試想如果上圖中一圈全有元素了,那麼rear會指向front的那個位置,這時就會出現fro
nt==
rear
front==rear
front=
=rea
r的情況。不覺得眼熟嘛~這就是判斷隊空的條件啊。
所以,如果不在陣列中留乙個空位置的話,隊滿和隊空無法區分。
我看很多教程都會定義乙個佇列的結構體,確實很規範。我把其中的基本原理和操作放在這裡,用起來會比較靈活。以後要寫結構體的話應該也會吧hhhhh
配套練習leetcode127. 單詞接龍 。看懂就要用啊~
迴圈佇列 C語言
佇列的特點是先進先出。在佇列的儲存過程中,不僅使用了一組位址連續的儲存單元存放從佇列頭到佇列尾的元素,而且還附設了兩個指標front和rear,分別指示佇列頭元素及佇列尾元素的位置。佇列操作示意圖 出自嚴蔚敏版資料結構 對鍊錶的增加是通過移動rear指標,鍊錶的刪除時通過移動front的移動。通過這...
迴圈佇列實現(C語言)
背景 生活中有很多佇列的影子,比如打飯排隊,買火車票排隊問題等,可以說與時間相關的問題,一般都會涉及到佇列問題 從生活中,可以抽象出佇列的概念,佇列就是乙個能夠實現 先進先出 的儲存結構。佇列分為鏈式佇列和靜態佇列 靜態佇列一般用陣列來實現,但此時的佇列必須是迴圈佇列,否則會造成巨大的記憶體浪費 鏈...
mysql迴圈佇列 C語言實現 迴圈佇列
include include include typedef struct queue int pbase 陣列 int front 頭 int rear 尾 rear不存放資料,所以rear前面的是最後乙個資料 queue void init queue queue pq bool full q...