JavaScript實現棧結構

參考資料

一.什麼是棧(stack)?

1.1.簡介

首先我們需要知道數組是一種線性結構,並且可以在數組的任意位置插入和刪除數據,而棧(stack)是一種受限的線性結構。以上可能比較難以理解,什麼是受限制的線性結構?讓我們首先來了解下棧結構的特點吧,下面就是棧的圖解:

總結棧的特點就是在放入數據的過程中是先進後出,後進後出(LIFO:last in first out)

1.2.程序中的棧實現

  • 函數調用棧:A(B(C(D))),既A函數中調用B,B調用C,C調用D;在A執行的過程中將A壓入棧,隨後B執行時B也被壓入棧,同理C和D執行時也會被壓入棧。所有當前棧的順序是:A->B->C->D(棧頂);同時D因爲在棧頂,在先執行完後,會彈出棧被釋放,因此彈出棧的順序爲:D->C->B->A

  • 遞歸:爲什麼說遞歸也是棧的實現方式呢?因爲在遞歸的使用時如果未設置停止遞歸的條件就會造成棧溢出!因爲遞歸也是的調用自身就是一種函數調用棧,因此如果未停止,會一直調用自身,不會把函數彈出棧,不停的將函數壓入棧,最好造成棧溢出!(Stack OverFloat)

1.3.一道面試題理解棧結構


首先我們來分析題目:六個元素順序進棧,注意只是順序進棧,並沒有說是同時進入喲,可能有進有出,如果同時豈不是考的太簡單了?哈哈,是不是嘛,所有我們要根據答案來一一判斷。

  • A:65進棧-5出棧-4進棧出棧-3進棧出棧-6出棧-21進棧(符合入棧順序654321)
  • B:654進棧-4出棧-5出棧-3進棧出棧-2進棧出棧-1進棧出棧-6出棧(符合)
  • C:6543進棧-3出棧-4出棧-6出棧(此處不符合,理論上不應該是6,6上面還有5未出棧)
  • D:65432進棧-2出棧-3出棧-4出棧-1進棧出棧-5出棧-6出棧(符合)

綜上所述,答案是 C

二.棧結構實現

2.1.棧的封裝

首先我們先需瞭解棧常見的操作有哪些?

  • push(element): 添加一個新元素到棧頂位置.
  • pop():移除棧頂的元素,同時返回被移除的元素。
  • peek():返回棧頂的元素,不對棧做任何修改(這個方法不會移除棧頂的元素,僅僅返回它)。
  • isEmpty():如果棧裏沒有任何元素就返回true,否則返回false。
  • clear():移除棧裏的所有元素。
  • size():返回棧裏的元素個數。這個方法和數組的length屬性很類似。

封裝代碼如下:

// 封裝棧類
      function Stack() {
        // 棧中的屬性
        this.items = []

        // 棧的相關操作
        // 1.將元素壓入棧
        Stack.prototype.push = function (element) {
          this.items.push(element)
        }

        // 2.從棧中取出元素
        Stack.prototype.pop = function () {
          return this.items.pop()
        }

        // 3.查看一下棧頂元素
        Stack.prototype.peek = function () {
          return this.items[this.items.length - 1]
        }

        // 4.判斷棧是否爲空
        Stack.prototype.isEmpty = function () {
          return this.items.length == 0
        }

        // 5.獲取棧中元素的個數
        Stack.prototype.size = function () {
          return this.items.length
        }

        // 6.toString方法
        Stack.prototype.toString = function () {
          // 形式自定 1 2 3 4 5
          var resultString = ''
          this.items.forEach((element) => {
            resultString += element + ' '
          })
          return resultString
        }
      }

測試代碼:

      // 棧的使用
      var s = new Stack()
      s.push(1)
      s.push(2)
      s.push(3)
      s.push(4)
      console.log(s.items) // [1,2,3,4]
      s.pop()
      console.log(s.items) // [1,2,3]
      console.log(s.peek()) // 3
      console.log(s.isEmpty()) // false
      console.log(s.size()) // 3
      console.log(s.toString()) // 1 2 3 (String)

2.2.棧結構的簡單應用(十進制轉二進制)

首先你必須要理解十進制轉二進制的方法,除以二取餘,一直除到結果爲0爲止。舉個例子吧,把10進制的數字10轉換爲二進制的數字,過程大概是如下流程:

結果就是1010,就是將餘數類似棧的方式依次取出來

  • 如果我們希望通過代碼來實現這個過程呢?
      // 封裝十進制轉二進制的函數
      function dec2bin(decNumber) {
        // 1.定義棧對象,上文封裝的棧類
        var stack = new Stack()
        // 2.循環操作
        while (decNumber > 0) {
          // 2.1獲取餘數,並且放入棧中
          stack.push(decNumber % 2)
          // 2.2更新decNumber,獲取整除後的結果,作爲下一次運行的數字
          decNumber = Math.floor(decNumber / 2)
        }
        // 3.從棧中取出0和1
        let binaryString = ''
        while (!stack.isEmpty()) {
          binaryString += stack.pop()
        }
        return binaryString
      }

測試代碼:

      // 測試代碼
      console.log(dec2bin(10)) //1010
      console.log(dec2bin(100)) //1100100

三.總結

看完是否對棧結構有一個清晰的瞭解?記住後進先出(LIFO:last farst in out)!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章