資料結構 第7講 迴圈佇列

2021-08-18 10:22:59 字數 4120 閱讀 7927

資料結構 第7講 迴圈佇列

過了一段時間,小張再也受不了這種"起早貪黑"的有車生活。為了解決胡同停車問題,小張跑了無數次居委會,終於將擋在胡同口的建築清除,這樣住在胡同盡頭的小張,就可以早早回家停在家門口,每天第乙個開車上班去了。

現在胡同打通了,但仍然很窄,只能通過一輛車,但是可以從一端進,另一端出,畫圖:

小汽車是線性排列,而且只能從一端進,另一端出,這就是"佇列",佇列也是一種線性表,只不過它是操作受限的線性表,只能在兩端操作,先進先出(first in first out,fifo)。

進的一端稱為隊尾(rear),出的一端稱為隊頭(front)。佇列可以用順序儲存,也可以用鏈式儲存。

1. 順序佇列

佇列的順序儲存形式,可以用乙個一維陣列儲存資料元素,用兩個整型變數記錄隊頭和隊尾元素的下標。

順序儲存方式:

順序佇列的結構體定義:

2. 完美**

接下來看看順序佇列的入隊和出隊情況:

假設現在順序佇列q分配了6個空間,然後進行入隊出隊操作,過程如圖所示:

(1) 開始時為空隊,q.front=q.rear,如圖所示:

(2) 元素a1進隊,放入尾指標q.rear(整型下標)的位置,q.rear後移一位,如圖所示:

(3) 元素a2進隊,放入尾指標q.rear(整型下標)的位置,q.rear後移一位,如圖所示:

(4) 元素a3,a4,a5分別按順序進隊,尾指標q.rear依次後移,如圖所示:

(5) 元素a1出隊,頭指標q.front(整型下標)後移一位,如圖所示:

(6) 元素a2出隊,頭指標q.front(整型下標)後移一位,如圖所示:

(7) 元素a6進隊,放入尾指標rear(整型下標)的位置,rear後移一位,如圖所示:

(8) 元素a7進隊,此時尾指標q.rear已經超過了陣列的下標,無法再儲存進隊,但是我們發現前面明明有2個空間,卻出現了隊滿的情況,這種情況稱為"假溢位"。

那麼如何解決該問題呢?

能否利用前面的空間繼續儲存入隊呢?

試試看…~

上面第(7)步元素a6進隊之後,尾指標q.rear要後移乙個位置,此時已經超過了陣列的下標,即q.rear+1=maxsize(最大空間數6),那麼如果前面有空閒,q.rear可以轉向前面0的位置,如圖所示:

然後元素a7進隊,放入尾指標q.rear(整型下標)的位置,q.rear後移一位,如圖所示:

元素a8進隊,放入尾指標q.rear(整型下標)的位置,q.rear後移一位,如圖所示:

這時候雖然佇列空間存滿了,但是出現了乙個大問題,隊滿時q.front=q.rear,這和隊空的條件一模一樣,無法區分隊空還是隊滿,如何解決呢?有兩種辦法:一是設定乙個標誌,標記隊空和隊滿;另一種辦法是浪費乙個空間,當尾指標q.rear的下乙個位置q.front是時,就認為是隊滿。如圖所示:

3. 迴圈佇列

上述到達尾部又向前儲存的佇列稱為迴圈佇列,為了避免"假溢位",我們通常採用迴圈佇列。

迴圈佇列無論入隊還是出隊,隊尾、隊頭加1後都要取模運算,例如入隊後隊尾後移一位:q.rear =(q.rear+1)%maxsize。

為什麼要%maxsize呢?

隊空 隊滿

上圖中最大空間maxsize,當q.rear=maxsize-1時,(q.rear+1)%maxsize=0,而且q.front=0,正好滿足隊滿的條件:(q.rear+1) %maxsize= q.front,此時為隊滿。

因此無論是front還是rear向後移動乙個位置時,都要加1與最大空間maxsize取模運算,處理臨界問題。

總結:

隊空:q.front=q.rear; // q.rear和q.front指向同乙個位置

隊滿: (q.rear+1) %maxsize=q.front; // q.rear向後移一位正好是q.front

入隊

q.base[q.rear]=x; //將元素放入q.rear所指空間,

q.rear =( q.rear+1) %maxsize; // q.rear向後移一位

出隊

e= q.base[q.front]; //用變數記錄q.front所指元素,

q.front=(q.front+1) %maxsize // q. front向後移一位

迴圈佇列中到底存了多少個元素呢?

因為佇列是迴圈的,所以存在兩種情況:

(1)q.rear>= q.front,如下圖所示:

這種情況佇列中元素個數為:q.rear-q.front=4-1=3。

(2)q.rear< q.front,如下圖所示:

此時,q.rear=4,q.front=maxsize-2,q.rear-q.front=6-maxsize。但是我們可以看到迴圈佇列中的元素實際上為6個,那怎麼辦呢?當兩者之差為負數時,可以將差值+maxsize計算元素個數,即:q.rear-q.front+maxsize=6-maxsize+maxsize =6,元素個數為6。

那麼在計算元素個數時,可以分兩種情況判斷:

也可以採用取模的方法把兩種情況統一為乙個語句:

佇列中元素個數:(q.rear-q.front+maxsize)% maxsize

當q.rear-q.front為負數時,加上maxsize再取餘正好是元素個數,如(-2+6)%6=4;當q.rear-q.front為正數時,加上maxsize超過了最大空間數,取餘後正好是元素個數,如(3+6)%6=3。

4. 佇列的基本操作

佇列的基本操作包括初始化、入隊、出隊、取隊頭元素、求佇列長度。

(1)初始化

//迴圈佇列的初始化

bool initqueue(sqqueue &q)//注意使用引用引數,否則出了函式,其改變無效

(2)入隊

bool enqueue(sqqueue &q,int e)//將元素e放入q的隊尾

(3)出隊

bool dequeue(sqqueue &q, int &e) //刪除q的隊頭元素,用e返回其值

(4)取隊頭元素

int gethead(sqqueue q)//返回q的隊頭元素,不修改隊頭指標

(5)迴圈佇列的長度

int queuelength(sqqueue q)

資料結構 第7講 迴圈佇列

資料結構 第7講 迴圈佇列 過了一段時間,小張再也受不了這種 起早貪黑 的有車生活。為了解決胡同停車問題,小張跑了無數次居委會,終於將擋在胡同口的建築清除,這樣住在胡同盡頭的小張,就可以早早回家停在家門口,每天第乙個開車上班去了。現在胡同打通了,但仍然很窄,只能通過一輛車,但是可以從一端進,另一端出...

資料結構 佇列 迴圈佇列

在佇列的陣列實現中,我們很容易發現數在出隊後,陣列的前面部分會有剩餘空間沒有被使用,所以我們為了最大程度的利用固定長度的陣列,我們採用迴圈佇列的儲存方式,這種方式的最大問題在於resize的時候比較麻煩,所以我們不考慮resize的情況。基本結構如下,這裡front指向第乙個元素的位置,rear指向...

資料結構 佇列 迴圈佇列

資料結構 佇列 迴圈佇列 順序儲存 犧牲乙個空間單元來判段佇列滿狀態。q.front q.rear 1 initsize date 2017 4 16 include define elemtype char define initsize 100 typedef structsqqueue voi...