定義
隊列是一種特殊的線性表,特殊之處在於它只允許在表的前端(front)進行刪除操作,而在表的後端(rear)進行插入操作,和棧一樣,隊列是一種操作受限制的線性表。進行插入操作的端稱爲隊尾,進行刪除操作的端稱爲隊頭。隊列的數據元素又稱爲隊列元素。在隊列中插入一個隊列元素稱爲入隊,從隊列中刪除一個隊列元素稱爲出隊。因爲隊列只允許在一端插入,在另一端刪除,所以只有最早進入隊列的元素才能最先從隊列中刪除,故隊列又稱爲先進先出的線性表
線性表:(linear list)是數據結構的一種,一個線性表是n個具有相同特性的數據元素的有限序列。
隊列又分爲兩種,分別是順序隊列和循環隊列
順序隊列
建立順序隊列結構必須爲其靜態分配或動態申請一片連續的存儲空間,並設置兩個指針進行管理。一個是隊頭指針front,它指向隊頭元素;另一個是隊尾指針rear,它指向下一個入隊元素的存儲位置,如圖所示,
每次在隊尾插入一個元素是,rear增1;每次在隊頭刪除一個元素時,front增1。隨着插入和刪除操作的進行,隊列元素的個數不斷變化,隊列所佔的存儲空間也在爲隊列結構所分配的連續空間中移動。當front=rear時,隊列中沒有任何元素,稱爲空隊列。當rear增加到指向分配的連續空間之外時,隊列無法再插入新元素,但這時往往還有大量可用空間未被佔用,這些空間是已經出隊的隊列元素曾經佔用過得存儲單元。
實現(數組)
function ArrayQueue(){ var arr = []; //入隊操作 this.push = function(element){ arr.push(element); return true; } //出隊操作 this.pop = function(){ return arr.shift(); } //獲取隊首 this.getFront = function(){ return arr[0]; } //獲取隊尾 this.getRear = function(){ return arr[arr.length - 1] } //清空隊列 this.clear = function(){ arr = []; } //獲取隊長 this.size = function(){ return length; } }
循環隊列
其操作表現基於 FIFO(先進先出)原則並且隊尾被連接在隊首之後以形成一個循環。它也被稱爲“環形緩衝器”。
在實際使用隊列時,爲了使隊列空間能重複使用,往往對隊列的使用方法稍加改進:無論插入或刪除,一旦rear指針增1或front指針增1 時超出了所分配的隊列空間,就讓它指向這片連續空間的起始位置。自己真從MaxSize-1增1變到0,可用取餘運算rear%MaxSize和front%MaxSize來實現。這實際上是把隊列空間想象成一個環形空間,環形空間中的存儲單元循環使用,用這種方法管理的隊列也就稱爲循環隊列。除了一些簡單應用之外,真正實用的隊列是循環隊列。 [2]
在循環隊列中,當隊列爲空時,有front=rear,而當所有隊列空間全佔滿時,也有front=rear。爲了區別這兩種情況,規定循環隊列最多隻能有MaxSize-1個隊列元素,當循環隊列中只剩下一個空存儲單元時,隊列就已經滿了。因此,隊列判空的條件時front=rear,而隊列判滿的條件時front=(rear+1)%MaxSize。隊空和隊滿的情況如圖:
實現(ES6)
class MyCircularQueue { constructor(size) { this.size = size; this.queue = []; } enQueue(value) { if (this.isFull()) return false; this.queue.push(value); return true; } deQueue() { if (this.isEmpty()) return false; this.queue.shift(); return true; } Front() { if (this.isEmpty()) return -1; return this.queue[0]; } Rear() { if (this.isEmpty()) return -1; return this.queue[this.queue.length - 1]; } isEmpty() { return this.queue.length === 0; } isFull() { return this.queue.length === this.size; } }