js數據結構-隊列

隊列

上一篇數據結構講到了棧,隊列和棧很是相似。隊列也是一種特殊的列表,它與棧的區別在於,棧是先入後出,而隊列則是遵循FIFO先入先出的原則,換言之隊列只能在隊尾插入元素,而在隊列的頭部去刪除元素。數據結構

舉個簡單的例子,隊列就至關於在生活中排隊購物,後來的人須要排在隊尾,而隊伍最前面的人會一次結帳後出列。隊列的應用很是普遍,經常使用於實現緩衝區,廣度優先搜索,優先級隊列等等。ui

隊列最主要的兩個操做分別是enqueue(入列)和dequeue(出列)this

隊列的實現邏輯

圖片描述

經過上面這張圖咱們能夠看到隊列的幾個特色spa

  • 初始化指針

    • 有一塊連續的空間用來去存儲隊列
    • 有一個頭部指向第一個數據的地址
    • 有一個尾部指向數據後一個空位的地址
    • 空間的大小
    • 隊列內部數據的長度
class Queue {
        constructor(max=1000){
            // 定義一塊連續的存儲空間用來存儲數據
            this.data = new Array(1000);
            // 開闢的空間大小
            this.max = max;
            // 頭部位置
            this.head = 0;
            // 尾部位置
            this.tail = 0;
            // 數據長度
            this.size = 0;
        }
    }
  • enqueue 入列code

    • 當數據長度超出了開闢的空間大小會報overflow的錯誤
    • 向尾部添加新數據
    • 尾部指針向後挪動一位,若是尾部沒有空間,則指向0(見上圖的兩個enqueue操做)
enqueue(x) {
        // 溢出
        if(this.size === this.max){
            throw 'overflow'
        }
        // 添加新數據到尾部
        this.data[this.tail] = x;
        // 數據長度+1
        this.size++;
        // 尾部指針向後挪動一位,若是後面沒有空間,則指向0
        if(this.tail === this.max-1){
            this.tail = 0;
        }else{
            this.tail++
        }
    }
  • dequeue出列blog

    • 若是當前數據長度爲0,則拋出underflow的錯誤
    • 取出頭部位置的數據
    • 頭部指針向後挪動一位
    • 數據長度-1
    • 返回該數據
dequeue(){
        if(this.size === 0){
            throw 'underflow';
        }
        const x = this.data[this.head];
        this.head++;
        this.size--;
        return x;
    }

整個代碼

class Queue {
      constructor(max = 1000) {
        this.data = new Array(max);
        this.max = max;
        this.head = 0;
        this.tail = 0;
        this.size = 0;
      }
    
      // 入列
      enqueue(x) {
        if (this.size === this.max) {
          throw 'overflow';
        }
        this.data[this.tail] = x;
        this.size++;
        if (this.tail === this.max - 1) {
          this.tail = 0;
        } else {
          this.tail++;
        }
      }
    
      // 出列
      dequeue() {
        if (this.size === 0) {
          throw 'underflow';
        }
        const x = this.data[this.head];
        this.head++;
        this.size--;
        return x;
      }
    
      get length() {
        return this.size;
      }
    }
    
    module.exports = Queue;

擴展--棧實現隊列

隊列也能夠經過兩個棧來實現,不瞭解棧的同窗能夠看上一篇關於棧文章,接下來會引入以前寫好的棧,具體代碼見下面。隊列

// 上一節中,棧的實現代碼
    const Stack = require('./stack');
    
    class Queue {
        constructor(max=1000){
            // 實例化兩個棧,分別是s1和s2, s1棧用來作入列,s2棧用來出列使用
            this.s1 = new Stack(max);
            this.s2 = new Stack(max);
            this.max = max;
        }
        // 入列
        enqueue(x) {
            if(this.s1.length === this.max){
                throw 'overflow'
            }
            // s1做爲入列
            this.s1.push(x);
        }
        // 出列
        dequeue(){
            if(this.s2.length>0){
                return this.s2.pop;
            }
            while(this.s1.length){
                this.s2.push(this.s1.pop());
            }
            return this.s2.pop();
        }
    }

在這裏大體簡單的說明一下以上用兩個棧來實現隊列的邏輯吧。圖片

  • 棧s1 入棧後假設數據爲 1,2,3,4,5,隊列遵循先入先出,因此dequeue的時候的順序應該是1,2,3,4,5,那麼下面咱們看如何利用棧s2出棧。
  • 首先棧s1 pop()出棧後的數據則爲 5,4,3,2,1 正好倒過來, 咱們利用循環將棧s1出棧的數據push到棧s2,則棧s2中的數據就會是5,4,3,2,1。下面咱們再執行s2.pop()的時候,是否是就能恰好能依次拿到1,2,3,4,5這幾個數據了

後續

下一張的數據結構會爲你們介紹鏈表get

相關文章
相關標籤/搜索