《資料結構與演算法之美》06 佇列

2022-07-01 19:03:09 字數 2947 閱讀 8547

一、概念

佇列:先進者先出。與棧一樣,也是一種受限的線性表,同樣有兩個基本操作:入隊和出隊。

二、佇列實現

佇列有兩種實現方式:順序佇列和鏈式佇列。

順序佇列

用陣列實現的佇列叫作順序佇列。

需要兩個指標:head指標和

tail

指標,分別指向隊頭和隊尾。

隨著入隊和出隊操作,head和

tail

會移到最右邊,即便還有空閒空間,也不通用再入隊了。這時候要用資料搬移。在入隊時,把資料陣列前端移動。

// 用陣列實現的隊列

public class arrayqueue

// 入隊

public bool enqueue(string item)

// 搬移完之後重新更新head和tail

tail -= head;

head = 0;

}items[tail] = item;

++tail;

return true;

}// 出隊

public string dequeue()

}

鏈式佇列

用鍊錶實現的佇列叫作鏈式佇列。

需要兩個指標:head指標和

tail

指標,分別指向鍊錶第乙個結點和最後乙個結點。

// 入隊

public bool enqueue(string item)

// 第一次入隊

if (head == null || tail == null)

else

--n;

return true;

}// 出隊

public string dequeue()

public class mylinkedlistnode

public string data

public mylinkedlistnode next }}

迴圈佇列

上面的陣列實現,在tail==n時,會有資料搬移操作,這樣入隊操作效能就會受到影響。

迴圈佇列是一種特殊的佇列,長得像個環,原來陣列是有頭有尾的,是一條直線,現在把首尾相連,形成乙個環,如下圖:

佇列空的條件:head==tail

佇列滿的條件:(tail+1)%n=head

public class circularqueue

// 入隊

public bool enqueue(string item)

// 出隊

public string dequeue()

}

注:迴圈佇列的關鍵要確定好隊空和隊滿的判定條件。

三、阻塞佇列和併發佇列

阻塞佇列就是在佇列基礎上增加了阻塞操作。簡單來說,就是在隊列為空的時候,從隊頭取資料會被阻塞。

可以使用阻塞佇列來實現「生產者

-消費者模型」。

通過協調「生產者」和

「消費者

」的個數,來提高資料的處理效率。

併發佇列就是要求執行緒安全的佇列。通過在enqueue()和

dequeue()

方法上加鎖。

四、執行緒池實現

有兩種處理策略。

1、非阻塞的處理方式,直接拒絕任務請求。

2、阻塞的處理方式,將請求排除,等有空閒執行緒時,取出請求繼續處理。

而佇列有兩種實現方式:基於陣列和基於鍊錶。

基於鍊錶,可以實現乙個支援無限排除的無界佇列,但可能會導致響應時間過長,對於響應時間比較敏感的系統,不適合採用這種方式。

基於陣列實現的有界佇列,佇列的大小有限,超過佇列大小時會拒絕請求,但設定乙個合理的佇列大小是非常講究的,既不能太大,也不能太小而無法充分利用資源,發揮最大效能。

對於大部分資源有限的場景,當沒有空閒資源時,基本上都可以通過「佇列

」這種資料結構來實現請求排除。

五、課後思考

1. 除了執行緒池這種池結構會用到隊列排隊請求,你還知道有哪些類似的池結構或者場景中會用到隊列的排隊請求呢?

比如資料庫連續池、web應該的請求佇列等。

2. 今天講到併發隊列,關於如何實現無鎖併發隊列,網上有非常多的討論。對這個問題,你怎麼看呢?

在多執行緒高併發程式設計的時候,最關鍵的問題就是保證共享物件的安全訪問。通常是用synchronized 來處理,其實加鎖本質上是將併發轉變為序列來實現的,勢必會影響吞吐量。

而最高效的做法就是不加鎖,那就是cas,

compare and swap

即比較並替換,設計併發演算法時常用到的一種技術。

cas實現原理:

cas有三個運算元:記憶體值

v、舊的預期值

a、要修改的值

b,當且僅當預期值

a和記憶體值

v相同時,將記憶體值修改為

b並返回

true

,否則什麼都不做並返回

false

資料結構 06佇列

只能在表的一端進行插入,另一端進行刪除,且具有先進先出原則的線性表稱為佇列。若用 s a1,a 2,a3 an s a 1,a 2,a 3,a n s a1 a2 a3 an 表示佇列,則 佇列常見的兩種操作 限定插入和刪除操作在表的兩端進行的線性表稱為雙端佇列。雙端佇列又可以分為 佇列基本操作用順...

資料結構和演算法之美 09 佇列

佇列 queue 先進者先出,這就是典型的 佇列 ps 無論順序佇列還是鏈式佇列,隊首指標指向佇列中第乙個元素,隊尾指標指向佇列的最後乙個元素的下乙個位置。入隊時,現將元素入隊,再將隊尾指標後移一位。作為一種非常基礎的資料結構,佇列的應用也非常廣泛,特別是一些具有某些額外特性的佇列,比如迴圈佇列 阻...

資料結構與演算法之美06

個人學習筆記總結,詳見資料結構與演算法之美 度娘 線性表 非線性表 陣列 1 儲存結構 鏈式儲存,前驅後繼關聯 2 操作 crud 前後索引關聯,涉及最優最糟問題 特點 非常低效 查詢操作 了解其儲存方式,即查詢就是通過陣列下標進行。插入操作 假設陣列的長度為n,現在,如果我們需要將乙個資料插入到陣...