程式猿必修課之資料結構(八)佇列

2021-08-23 12:13:36 字數 2332 閱讀 7423

佇列(queue)是只允許在一端進行插入操作,而在另一端進行刪除操作的線性表。

佇列是一種先進先出(first in first out)的線性表,簡稱fifo。允許插入的一端稱為隊尾,允許刪除的一端稱為隊頭。

佇列是特殊的線性表,因此它的各種操作類似線性表,不同的是插入資料只能在隊尾進行,刪除資料只能在隊頭進行。

adt 佇列(queue)

data

同線性表。元素的型別相同,相鄰元素具有前驅和後繼關係。

operation

initqueue(*q): 佇列初始化,建立乙個空佇列。

destroyqueue(*q): 若佇列 q 存在,就銷毀它。

clearqueue(*q): 將佇列清空。

isempty(*q): 若隊列為空,返回 true;否則返回 false。

gethead(q, *e): 若佇列 q 存在且不為空,則用 e 返回佇列 q 中的隊頭元素。

enqueue(*q, e): 若佇列 que 存在,插入新元素 e 到佇列 q 中並成為隊尾元素。

dequeue(*q, *e): 刪除佇列 q 中隊頭元素,並用 e 返回。

getlength(q): 返回佇列 q 的元素個數。

endadt

我們把頭尾相接的佇列的順序儲存結構稱為迴圈佇列。

用 front 指標指向隊頭元素,用 rear 指標指向隊尾元素的下乙個位置(為了避免陣列越界,隊尾元素後要留乙個空閒單元,儲存 rear 指標)。所以當 front == rear 時,表示隊列為空;當陣列中只有乙個空閒單元時佇列就滿了。

因為是迴圈佇列,所以 rear 可能比 front 大,也可能比 fornt 小,如下圖所示:

可以看出,它們可能只相差乙個位置,但也可能相差整整一圈。所以若佇列的最大容量為 queuesize,那麼佇列滿的條件是:(rear + 1) % queuesize == front。

當 rear > front 時(即左圖),佇列的長度為 rear - front;當 rear < front 時(即右圖),佇列的長度由兩部分構成,一部分是 queuesize - front,另一部分是 0 + rear,所以佇列長度為 rear - front + queuesize。所以通用的計算佇列長度的公式為:

(rear - front + queuesize) % queuesize

define maxsize 10

typedef struct queue;

初始化:

void initqueue(queue *q)
求佇列長度

int queuelength(queue q)
入隊操作:

boolean enqueue(queue *q, int e)
出隊操作:

boolean dequeue(queue *q, int *e)
雖然迴圈佇列解決了出隊時演算法的時間複雜度不高的問題,但是它仍然有陣列可能會溢位的問題,所以還需要鏈式儲存結構來解決這個問題。

佇列的鏈式儲存結構,其實就是線性表的單鏈表,只不過它只能尾進頭出而已,簡稱為鏈佇列。

為了方便操作,隊頭指標指向鏈佇列的頭結點;尾指標指向終端結點。當 front 和 rear 都指向頭結點時,隊列為空。

鏈佇列的結構為:

typedef struct qnode qnode, *pqueue;

typedef structlinkqueue;

boolean enqueue(linkqueue *q, int e)
出隊操作就是頭結點的後繼結點 p 出隊,將頭結點的後繼改為 p 的後繼結點,如果p 是 rear 指向的結點,那麼還要將 rear 指向頭結點。

boolean dequeue(linkqueue *q, int *e)
從時間複雜度,它們的基本操作都是 o(1);但是迴圈佇列需要先申請好空間,使用期間不釋放,而對於鏈佇列,每次申請和釋放結點也會存在一些時間開銷。

從空間上來說,迴圈佇列必須有乙個固定的長度,這樣就可能存在空間浪費的問題;而鏈佇列不存在這個問題,儘管它需要乙個指標域。

總的來說,在可以確定佇列長度最大值的情況下,建議用迴圈佇列,反之用鏈佇列。

程式猿必修課之資料結構(十)樹1

樹是一對多的資料結構 樹 tree 是 n n 0 個結點的有限集。n 0 時,稱為空樹。在任意一棵非空樹中 其實樹的定義用到了遞迴的方法。樹的每乙個結點包含乙個資料元素和若干個指向其子樹的分支。結點的度 結點擁有的子樹的個數稱為結點的度 degree 度為 0 的結點稱為葉結點 leaf 或終端結...

程式猿必修課之資料結構(七)棧2

斐波那契 fibonacci 是乙個經典的遞迴例子。數字 1,1,2,3,5,8,13.構成乙個序列,它的特點是 前面相鄰兩項之和是後一項的值。用數學函式來定義是 斐波那契數列 用遞迴實現列印出前 40 位的斐波那契數列數的 如下 includeint fbi int int main return...

程式猿必修課之資料結構(一)資料結構基本概念和術語

資料結構 是相互之間存在一種或多種特定關係的資料元素的集合。本文將 資料結構 分為 資料 和 結構 兩部分。程式設計 資料結構 演算法 資料 資料 是描述客觀事物的符號,是計算機中可以操作的物件,是能被計算機識別,並輸入給計算機處理的符號集合。也就是說,我們這裡說的資料其實就是符號,而且這些符號必須...