從應用場景看棧

諸葛林發表於2019-03-29

在 JavaScript 中,陣列就是一個最簡單的棧了,在尾部操作的poppush也對應著出入棧的操作。so ?

棧只是種抽象概念,用連結串列 or 其它方式實現它均可。應用之解決問題正是它存在的原因

場景一:遞迴

從前山上有座廟,廟裡有個老和尚和小和尚,老和尚給小和尚講故事:“從前山上有座廟......”

有名的斐波那契數列,手動地計算相當困難,即便有計算器在手。而在程式語言中,使用遞迴可以很好地解決這個難題:

function F(n) {
  return F(n-1) + F(n-2);
}
複製程式碼

重點來了,計算機如何實現遞迴?這是一個很籠統的概念,因為等於這個加那個,那個再加這個...... 知其所以然而不知其然。應用棧的結構,我們可以把未知的結果推入棧內,在彈出的時候逐個計算。 如下圖

棧應用 - 斐波那契數列

程式碼解釋:

function recursion() {
  // 呼叫棧
  const stack = [];

  // 解析時
  // 推入棧
  // 一般來說,棧有大小限制,如果自己寫了個無限遞迴的函式,那呼叫棧一直增加,最後溢位
  for (let i = n; i > 0; i--) {
    stack.push(F(i));
  }

  // 執行時
  // 後入先出,彈出
  for (let i = 3; i <= n; i++) {
    F(n-2) = stack.pop();
    F(n-1) = stack.pop();

    F(n) = F(n-1) + F(n-2)
    
    // 計算完成後再推入棧內
    stack.push(F(n))
  }

  // 執行完成,棧內剩下最終結果,彈出並返回
  if (n) return stack.pop()
}
複製程式碼

場景二:四則運算

數學老師:“先乘除,後加減,有括號先算括號。”

分析下計算機四則運算的步驟:

  1. 定義運算子功能
  2. 優先順序:乘除 >> 加減
  3. 有括號優先計算括號

示例:(1 + 2) x 3 - 4 ÷ 5

括號內優先計算,立馬得出結果,咋一想還蠻符合佇列的規則,先入先出嘛。但在有多個括號的情況下,優先計算最裡面的括號,這樣就只能推入棧中慢慢計算了。

但是怎麼優雅地推入棧內計算,有個偉大的科學家解決了這個難題,波蘭邏輯學家想到了一種不需要括號的字尾表示式,稱之為逆波蘭

示例字尾表示式:12+3*45/-

字尾表示式計算過程:

棧應用 - 字尾表示式計算

轉化後的計算簡直不要太簡單,來看看又是如何利用棧來轉的:

棧應用 - 四則運算

最後

直接從《大話資料結構》搬過來的磚。。。不過這本書真的比清華版資料結構易懂多了,正在啃的同學安利下

相關文章