前端學數據結構:棧和隊列

本文首發於 個人 Githubgit

棧遵循 後進先出 的原則。github

/** * 棧 * 後進先出 */
class Stack {
  constructor() {
    this.items = [];
  }

  // 添加元素
  push(value) {
    this.items.push(value);
  }

  // 返回棧頂的元素
  peek() {
    return this.items[this.items.length - 1];
  }

  // 移出棧頂的元素
  pop() {
    return this.items.pop();
  }
  
  /** * 判斷棧是否爲空 */
  isEmpty() {
    return this.items.length <= 0;
  }
}
複製代碼

隊列

隊列遵循 先進先出 的原則。this

/** * 隊列 * 先進先出 */
class Queue {
  constructor() {
    this.items = [];
  }

  /** * 添加元素 */
  enqueue(value) {
    this.items.push(value);
  }

  /** * 移出隊列的第一個元素 */
  dequeue() {
    return this.items.shift();
  }
}
複製代碼

常見題目

1. 有效的括號

問題描述

給定一個只包括 '(',')','{','}','[',']'的字符串,判斷字符串是否有效。spa

解題思路

使用 來解決。code

  • 遍歷字符串,若是是左括號便壓入棧中。
  • 若是遇到右括號,分類談論:
    1. 若是當前棧爲空,返回 false
    2. 取出棧頂元素,若是與之匹配繼續循環,不然返回 false
/** * 給定一個只包括 '(',')','{','}','[',']' 的字符串,判斷字符串是否有效。 * @param {*} str */
function isValidStr(str) {
  let arr = str.split("");
  let stack = new Stack();

  function isMatchStr(a, b) {
    return (
      (a === "(" && b === ")") ||
      (a === "[" && b === "]") ||
      (a === "{" && b === "}")
    );
  }

  while (arr.length) {
    let char = arr.shift();

    if (char === "(" || char === "[" || char === "{") {
      stack.push(char);
    } else {
      if (stack.isEmpty()) {
        return false;
      } else if (isMatchStr(stack.pop(), char)) {
        continue;
      } else {
        return false;
      }
    }
  }

  return true;
}
複製代碼

2. 用兩個棧實現隊列

問題描述

用兩個棧來實現一個隊列,完成隊列的 enqueuedequeue 操做。隊列

解題思路

in 棧用於處理 入列 操做,out 棧用於處理 出列 操做。字符串

  • 入列的值直接壓入 in
  • 出列時,將 in 棧的元素出棧壓入到 out 棧,而後返回 out 棧棧頂的元素(這樣便保持了隊列 先進先出 的原則)。
class TwoStackQueue {
  constructor() {
    this.inStack = new Stack();
    this.outStack = new Stack();
  }

  enqueue(value) {
    this.inStack.push(value);
  }

  dequeue() {
    while (!this.inStack.isEmpty()) {
      this.outStack.push(this.inStack.pop());
    }

    return this.outStack.pop();
  }
}
複製代碼

3. 棧的壓入、彈出序列

問題描述

輸入兩個整數序列,第一個序列表示棧的壓入順序,請判斷第二個序列是否爲該棧的彈出順序。假設壓入棧的全部數字均不相等。例如序列 1,2,3,4,5 是某棧的壓入順序,序列 4,5,3,2,1是該壓棧序列對應的一個彈出序列,但4,3,5,1,2就不多是該壓棧序列的彈出序列。(注意:這兩個序列的長度是相等的)get

解題思路

初始化一個輔助棧,遍歷壓入順序,執行入棧操做,入棧的同時,若是輔助棧非空,同時彈出序列的當前值與輔助棧棧頂元素相同,則輔助棧出棧。最後判斷輔助是否爲空,爲空這是正確的順序,不然不是。例如:string

入棧:1, 2, 3, 4, 5
出棧:4, 5, 3, 2, 1
it

首先,1 入棧,此時棧頂元素 1 != 4,繼續入棧;
2 != 4,入棧;
3 != 4 入棧;
4 == 4,入棧後出棧(這時候棧內元素爲 1, 2, 3);
3 != 5,入棧(這時候棧內元素爲 1, 2, 3, 5),5 == 5 出棧,3 == 3 出棧...
最後棧爲空,順序匹配。

function isPopOrder(pushOrder, popOrder) {
  let stack = new Stack();
  let popIndex = 0;

  for (let pushIndex = 0; pushIndex < pushOrder.length; pushIndex++) {
    stack.push(pushOrder[pushIndex]);

    while (!stack.isEmpty() && stack.peek() === popOrder[popIndex]) {
      stack.pop();
      popIndex++;
    }
  }

  return stack.isEmpty();
}
複製代碼
相關文章
相關標籤/搜索