每週一練 之 數據結構與算法(Queue)

這是第二週的練習題,這裏補充下咯,五一節立刻就要到了,本身的計劃先安排上了,開發一個有趣的玩意兒。前端

下面是以前分享的連接:git

歡迎關注個人 我的主頁 && 我的博客 && 我的知識庫 && 微信公衆號「前端自習課」github

本週練習內容:數據結構與算法 —— Queue算法

這些都是數據結構與算法,一部分方法是團隊其餘成員實現的,一部分我本身作的,有什麼其餘實現方法或錯誤,歡迎各位大佬指點,感謝。後端

1、隊列有什麼特色,生活中有什麼例子?


解題:
1.概念介紹數組

隊列,又稱爲佇列(queue),是先進先出(FIFO, First-In-First-Out)的線性表。在具體應用中一般用鏈表或者數組來實現。隊列只容許在後端(稱爲rear)進行插入操做,在前端(稱爲front)進行刪除操做。 ——《維基百科》bash

隊列特色:先進先出操做。
生活中的案例:常見的排隊,在電影院也好,排隊結帳也是,排在第一位的人會先接受服務。微信

2.與堆棧區別
隊列的操做方式和堆棧相似,惟一的區別在於隊列只容許新數據在後端進行添加。數據結構

2、請實現一個隊列,並實現如下方法:

  • enqueue(element):向隊列尾部添加一個新的項。
  • dequeue():移除隊列的第一項,並返回被移除的元素。
  • front():返回隊列中第一個元素 —— 最早被添加,也將是最早被移除的元素。隊列不作任何變更 (不移除元素,只返回元素信息 —— 與 Stack 類的 peek 方法相似)。
  • tail():返回隊列中的最後一個元素,隊列不作任何變更。
  • isEmpty():若是棧沒有任何元素就返回 true,不然返回 false
  • size():返回隊列包含的的元素個數,與數組的 length 屬性相似。
  • print():打印隊列中的元素。

提示:Web 端優先使用 ES6 以上的語法實現。post


解題:

/** * 2. 實現一個隊列 */
class Queue {
    constructor (){
        this.items = []
    }
    // enqueue(element):向隊列尾部添加一個新的項。
    enqueue( element ){
        this.items.push(element)
    }
    // dequeue():移除隊列的第一項,並返回被移除的元素。
    dequeue (){
        return this.items.shift()
    }
    // front():返回隊列中第一個元素 —— 最早被添加,也將是最早被移除的元素。隊列不作任何變更 (不移除元素,只返回元素信息 —— 與 Stack 類的 peek 方法相似)。
    front (){
        return this.items[0]
    }
    // tail():返回隊列中的最後一個元素,隊列不作任何變更。
    tail (){
        return this.items[this.items.length]
    }
    // isEmpty():若是棧沒有任何元素就返回 true,不然返回 false。
    isEmpty (){
        return this.items.length === 0
    }
    // size():返回隊列包含的的元素個數,與數組的 length 屬性相似。
    size (){
        return this.items.length
    }
    // print():打印隊列中的元素。
    print (){
        console.log(this.items.toString())
    }
}
複製代碼

3、使用隊列計算斐波那契數列的第 n 項。

斐波那契數列(Fibonacci sequence),又稱黃金分割數列、因數學家列昂納多·斐波那契(Leonardoda Fibonacci)以兔子繁殖爲例子而引入,故又稱爲「兔子數列」,指的是這樣一個數列:

1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,377,610...
複製代碼

在數學上,斐波那契數列以以下被以遞推的方法定義:F(1)=1,F(2)=1, F(n)=F(n-1)+F(n-2)(n>=3,n∈N,即前兩項固定爲 1*,後面的項爲前兩項之和,依次向後。在現代物理、準晶體結構、化學等領域,斐波納契數列都有直接的應用。

使用示例以下:

fibonacci(5); --> 5
fibonacci(9); --> 34
fibonacci(14); --> 377
複製代碼

解題:

解題方法1:

/** * 3. 使用隊列計算斐波那契數列的第 n 項。 * 前兩項固定爲 1,後面的項爲前兩項之和,依次向後。 * @param {Number} num */

function fibonacci (num){
    if(isNaN(num) || num < 0 || num === 0) return 0
    // // 1. 直接
    // let n1 = 1, n2 = 1, sum
    // for(let i = 3; i <= num; i++){
    // sum = n1 + n2
    // n1 = n2
    // n2 = sum
    // }
    // // 2. 隊列 考慮小於等於2
    // let arr = [], sum
    // num === 1 && (arr = [1])
    // num >= 2 && (arr = [1, 1])
    // for(let i = 3; i <= num; i ++){
    // sum = arr[i-2] + arr[i-3]
    // arr.push(sum)
    // }
    // // 3.隊列 進出隊列
    let queue = [], sum;
    for(let i = 1; i <= num; i ++){
        if(i <=2 ){
            queue.push(1)
        }else{
            sum = queue[0] + queue[1]
            queue.push(sum)
            queue.shift()
        }
    }
    return sum
}
複製代碼

解題方法2:

function fibonacci(n) {
    const queue = new Queue();
    queue.enqueue(1);
    queue.enqueue(1);
    
    let index = 0;
    while(index < n - 2) {
        index += 1;
        // 出隊列一個元素
        const delItem = queue.dequeue();
        // 獲取頭部值
        const headItem = queue.front();
        const nextItem = delItem + headItem;
        queue.enqueue(nextItem);
    }
    return queue.tail();  
}
console.log(fibonacci(9)); // 34
複製代碼

4、實現優先隊列 PriorityQueue。

現實中優先隊列的例子不少,好比機場登機的順序,頭等艙和商務艙乘客優先級高於經濟艙乘客。又如在銀行中辦理業務時,VIP 客戶的優先級高於普通客戶。要實現一個優先隊列,有兩種方式:

  1. 設置優先級,而後在正確的位置添加元素。
  2. 用入列操做添加元素,而後按照優先級移除它們。

本題要求使用第一種方式來實現優先隊列,數值越小優先級越高,若優先級相同時,先入隊的元素,排在前面。

使用示例以下:

let priorityQueue = new PriorityQueue();
priorityQueue.enqueue("leo", 2);
priorityQueue.enqueue("pingan", 1);
priorityQueue.enqueue("robin", 1);
priorityQueue.print();
// pingan - 1
// robin - 1
// leo - 2
複製代碼

解題:

解題方法1:

class PriorityQueue {
  constructor() {
    this._items = [];
  }
  
  enqueue(element, priority) {
        let queueElement = {
            element
            priority
        };

      if (this.isEmpty()) {
        this._items.push(queueElement);
      } else {
        let added = false;
        for (var i = 0; i < this.size(); i++) {
          if (queueElement.priority < this._items[i].priority) {
            this.items.splice(i, 0, queueElement);
            added = true;
            break ;
          }
        }
    
        if (!added) {
          this._items.push(queueElement);
        }
      }
  }

  print() {
      var strArr = [];
      strArr = this._items.map(function (item) {
        return `${item.element}->${item.priority}`;
      });
    
      console.log(strArr.toString()); 
      }
}
複製代碼

解題方法2:

/** * 4. 實現優先隊列 */

class PriorityQueue {
    constructor (){
        this.items = []
    }
    enqueue (element, priority){
        let ele = {element, priority}
        let isAdded = false
        for(let i = 0; i < this.items.length; i++){
            if(ele.priority < this.items[i].priority){
                this.items.splice(i, 0, ele)
                isAdded = true
                break
            }
        }
        !isAdded && this.items.push(ele)
    }
    print (){
        for(let i = 0; i < this.items.length; i++){
            let {element, priority} = this.items[i]
            console.log(`${element} - ${priority}`)
        }
    }
}
let leo = new PriorityQueue()
leo.enqueue("leo", 2);
leo.enqueue("leo1", 1);
leo.enqueue("leo2", 1);
console.log(leo)
複製代碼

5、用隊列實現棧。

利用兩個隊列實現棧,棧的特色是後進先出,可讓元素入隊 q1,留下隊尾元素讓其餘元素出隊,暫存到 q2 中,再讓 q1 中剩下的元素出隊,即最後進的最早出來。

提示:入棧和出棧都在 q1 中完成,q2 只做爲臨時中轉空間。


解題:

/** * 5. 隊列實現棧 */
class Myqueue {
    constructor (){
        this.items = []
    }
    enqueue (element){
        this.items.push(element)
    }
    dequeue (){
        return this.items.shift()
    }
}
class Mystack {
    constructor (){
        this.q1 = new myQueue()
        this.q2 = new myQueue()
    }
    push (element){
        this.q1.enqueue(element)
        this.q2.items = []
        let len = this.q1.items.length
        while(len > 0){
            this.q2.enqueue(this.q1.items[len-1])
            len --
        }
    }
    pop (){
        let result = this.q2.dequeue()
        let len = this.q2.items.length
        this.q1.items = []
        while(len > 0){
            this.q1.enqueue(this.q2.items[len-1])
            len --
        }
        return result
    }
    print (){
        console.log(this.q1.items.toString())
    }
}
複製代碼

這裏也能夠直接使用第二題定義的Queue來實現:

class QueueStack {
  constructor() {
    this.queue = new Queue();
  }

  push(item) {
    this.queue.enqueue(item);
  }

  pop() {
    // 向隊列末尾追加 隊列長度-1 次,後彈出隊列頭部
    for(let i = 1; i < this.queue.size(); i += 1) {
      this.queue.enqueue(this.queue.dequeue());
    }
    return this.queue.dequeue();
  }

  peek() {
    return this.queue.tail();
  }
}
複製代碼

下週預告

下週將練習集合(Set) 的題目,五一要到咯,也要好好作本身一個項目了。

相關文章
相關標籤/搜索