佇列(Queue)

文章目錄

介紹

佇列式資料結構的一種,類似堆疊,但佇列是在頭尾兩端最新增和刪除,數據就像在排隊,在隊伍中最晚到的人排在最後面,先到的人則優先處理(如下圖所示)。

佇列的幾個重點:

  • 先進先出的原理,稱為 First In First Out 縮寫為 FIFO
  • 元素沒有index
  • 從後面加入,從前面移除
  • Enqueue指的是新增東西至queueDequeue指的是從queue移除東西

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

(圖片來自於Queues)

實作Queue

JS Array實作

我們可以利用Array的方法模擬Queue,利用push模擬新客人來排隊,利用shift模擬最前面的客人已處理完成離開了。

let queue = []; queue.push(68); queue.push(50); queue.push(92); queue.push(29); queue.push(57); queue.push(88); queue.shift();

物件導向實作

初始化節點以及queue

Node節點有值以及可以知道他的下一個節點是誰

Queue 我們能知道他頭尾的節點以及長度為何

class Node { constructor(value) { this.value = value; this.next = null; } } class Queue { constructor() { this.head = null; this.tail = null; this.length = 0; } }

入隊enqueue

將新的值加到尾端

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

(圖片來自於visualgo)

  1. 新增新節點
  2. 如果頭為空,則將頭尾指向新節點
  3. 否則的話,舊尾端的下一個為新節點,再把新尾端指向新節點
  4. Queue長度加一
enqueue(value) { let newNode = new Node(value); if (this.head === null) { this.head = newNode; this.tail = newNode; } else { this.tail.next = newNode; this.tail = newNode; } this.length++; }

出隊dequeue

將最前端的值移出

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

(圖片來自於visualgo)

  1. 如果head為空則回傳null
  2. 如果queue長度為一則將head移除並回傳,並將頭尾及長度設為空
  3. 非上述兩項,代表queue長度大於一,則將head指向head的下一個,並將原先的head移出回傳,queue長度減一
dequeue() { if (this.head === null) { return null; } else if (this.length === 1) { let temp = this.head; this.head = null; this.tail = null; this.length = 0; return temp; } else { let temp = this.head; this.head = this.head.next; this.length--; return temp; } }

返回第一個

返回第一個的值,可以把它想像成最早排隊的

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

(圖片來自於visualgo)

  1. 如果head存在則回傳
  2. 否則回傳null
getHead() { if (this.head === null) { return null; } else { return this.head.value; } }

完整程式碼

class Node { constructor(value) { this.value = value; this.next = null; } } class Queue { constructor() { this.head = null; this.tail = null; this.length = 0; } enqueue(value) { let newNode = new Node(value); if (this.head === null) { this.head = newNode; this.tail = newNode; } else { this.tail.next = newNode; this.tail = newNode; } this.length++; } dequeue() { if (this.head === null) { return null; } else if (this.length === 1) { let temp = this.head; this.head = null; this.tail = null; this.length = 0; return temp; } else { let temp = this.head; this.head = this.head.next; this.length--; return temp; } } getHead() { if (this.head === null) { return null; } else { return this.head.value; } } printAll() { let current = this.head; while (current) { console.log(current.value); current = current.next; } } } let myQueue = new Queue(); myQueue.enqueue(68); myQueue.enqueue(50); myQueue.enqueue(92); myQueue.enqueue(29); myQueue.enqueue(57); myQueue.enqueue(88); myQueue.dequeue(); myQueue.getHead(); // 50 myQueue.printAll(); // 50, 92, 29, 57, 88

複雜度

時間複雜度

Action動作 平均 最壞
訪問(Access)
O(n)
O(n)
搜尋(Search)
O(n)
O(n)
插入(Insertion)
O(1)
O(1)
刪除(Deletion)
O(1)
O(1)

空間複雜度

O(n)

實戰

232. Implement Queue using Stacks

題目說明

僅使用兩個堆疊實現先進先出 (FIFO) 佇列。實現的佇列應該支持普通佇列的所有功能(push、peek、pop和empty)

Code

  1. push(x)- 將一個元素推x到佇列的後面。
  2. pop()- 從佇列的前面移除並返回元素。它通過首先將所有元素從轉移queuequeue2,從queue2彈出元素,然後將所有元素轉移回queue
  3. peek()- 返回佇列前面的元素而不刪除它。它首先將所有元素從轉移queuequeue2,檢索最後一個元素queue2,然後將所有元素轉移回queue
  4. empty()- 如果佇列為空則返回,false否則返回。
var MyQueue = function() { this.queue = [] this.queue2 = [] }; /** * Pushes element x to the back of the queue. * @param {number} x * @return {void} */ MyQueue.prototype.push = function(x) { this.queue.push(x) }; /** * Removes the element from in front of queue and returns that element. * @return {number} */ MyQueue.prototype.pop = function() { while(this.queue.length !== 0){ this.queue2.push(this.queue.pop()) } var pop = this.queue2.pop() while(this.queue2.length !== 0){ this.queue.push(this.queue2.pop()) } return pop }; /** * Returns the element at the front of the queue. * @return {number} */ MyQueue.prototype.peek = function() { while(this.queue.length !== 0){ this.queue2.push(this.queue.pop()) } var peek = this.queue2[this.queue2.length - 1] while(this.queue2.length !== 0){ this.queue.push(this.queue2.pop()) } return peek }; /** * Returns true if the queue is empty, false otherwise. * @return {boolean} */ MyQueue.prototype.empty = function() { return this.queue == 0 }; /** * Your MyQueue object will be instantiated and called as such: * var obj = new MyQueue() * obj.push(x) * var param_2 = obj.pop() * var param_3 = obj.peek() * var param_4 = obj.empty() */

@joe94113Tue, Feb 7, 2023 10:00 PM