做爲一個優秀的程序猿須要具備知識的廣度。首先是要了解你選擇的編程語言。若是你正在閱讀這篇文章,最有可能使用 JavaScript。javascript
然而在熟悉了編程語言以後,你還必須瞭解如何根據任務輕鬆且有效地操縱數據。這就是數據結構的用武之地。前端
在本文中,我將描述隊列數據這個結構:它都有哪些操做以及在 JavaScript 中怎樣實現。java
若是你喜歡四處旅行,確定在火車站經歷過檢票這道手續。若是有不少人要坐火車,那麼很天然地會造成一個隊列。剛進入車站的人加入隊列。另外一邊剛剛經過檢票的人從隊列中走出。這就是隊列的一個例子,與隊列數據結構的操做方式相同。程序員
隊列是一種遵循先入先出(FIFO)規則的數據結構。第一個進入隊列中的項目(輸入)是第一個出隊(輸出)的。面試
隊列有2個指針:隊首和隊尾。最早進入隊列進行排隊的項目位於隊首,而最後進入隊列的項目位於隊尾。編程
回顧車站的例子,第一個檢票的是在隊列的隊首。剛進入隊列的人在隊尾。segmentfault
從更高的層面來看,隊列是一種容許你按照前後順序處理項目的數據結構。服務器
隊列支持 2 個主要操做:入隊(enqueue)和出隊(dequeue),另外還有 peek 和 length 操做。微信
入隊操做在隊列的尾部插入項目,使其成爲隊列的隊尾。數據結構
上圖中的入隊操做在隊尾插入了 8
,以後 8
成爲隊列的隊尾。
queue.enqueue(8);
出隊操做取出隊列中第一個項目,此時隊列中的下一個項目成爲隊首。
在上圖中,出隊操做返回項目7
並從隊列中刪除。 出隊以後以後,項目 2
成爲新的隊首。
queue.dequeue(); // => 7
Peek 操做讀取隊首的項目,可是不改變隊列。
上圖中 7
是隊首。 peek 操做只需返回隊首 7
可是不修改隊列。
queue.peek(); // => 7
length 操做返回隊列中包含項目的數量。
上圖中的隊列有 4 項:4
、6
、2
和。7
。結果隊列長度爲 4
。
queue.length; // => 4
關於隊列全部操做的重點:enqueue,dequeue,peek 和 length 必須以常數時間複雜度 O(1)
執行。
常數時間複雜度 O(1)
意味着不管隊列大小如何(無論是有 10 個仍是 100 萬個項目),這些操做都必須在相對一致的時間內執行。
來看一下怎樣在保證全部操做必須以常數時間複雜度O(1)
要求實現隊列這種數據結構。
class Queue { constructor() { this.items = {}; this.headIndex = 0; this.tailIndex = 0; } enqueue(item) { this.items[this.tailIndex] = item; this.tailIndex++; } dequeue() { const item = this.items[this.headIndex]; delete this.items[this.headIndex]; this.headIndex++; return item; } peek() { return this.items[this.headIndex]; } get length() { return this.tailIndex - this.headIndex; } } const queue = new Queue(); queue.enqueue(7); queue.enqueue(2); queue.enqueue(6); queue.enqueue(4); queue.dequeue(); // => 7 queue.peek(); // => 2 queue.length; // => 3
const queue = new Queue()
是建立隊列的實例。
queue.enqueue(7)
方法將 7
存入隊列中。
queue.dequeue()
從隊列中取出一個頭部項目,而 queue.peek()
只讀隊首項。
最後的 Queue.Length
顯示隊列中還有多少個項目。
關於實現:在 Queue
類中,普通對象 this.Items
將隊列的項目經過數值索引保持。 隊首項的索引由 Where.HeadInex
跟蹤,隊尾項由 this.tailIndex
跟蹤。
在 Queue
的 queue()
、 dequeue()
、 peek()
和 length()
方法中存在:
this.items[this.headIndex]
),this.headidex++
)這些方法的時間複雜度是恆定的時間 O(1)
。
隊列是一種遵循先入先出(FIFO)規則的的數據結構。
隊列有 2 個主要操做:入隊和出隊。 另外,隊列能夠有輔助操做,例如 peek 和 length。
全部隊列操做都必須以常數時間 O(1)
執行。
挑戰一下:改進 dequeue()
和 peek()
方法,當在空隊列上執行時會拋出錯誤。