棧及棧的應用

棧及棧的應用

  • stack:稱做棧或堆疊,其特殊之處只容許在鏈表或數組的一端(堆棧頂端)插入(push)數據,輸出數據(pop)
  • 其特色是先進後出
  • image

棧的實現

<!--鏈表實現-->
import LinkedList from '../linked-list/LinkedList';

export default class Stack {
  constructor() {
    this.linkedList = new LinkedList();
  }

  /**
   * @return {boolean}
   */
  isEmpty() {
    return !this.linkedList.tail;
  }

  /**
   * @return {*}
   */
  peek() {
    if (!this.isEmpty()) {
      return null;
    }
    return this.linkedList.tail.value;
  }

  /**
   * @param {*} value
   */
  push(value) {
    this.linkedList.append(value);
  }

  /**
   * @return {*}
   */
  pop() {
    const tailNode = this.linkedList.deleteTail();
    return tailNode ? tailNode.value : null;
  }

  /**
   * @return {*[]}
   */
  toArray() {
    return this.linkedList
      .toArray()
      .map(linkedListNode => linkedListNode.value)
      .reverse();
  }

  /**
   * @param {function} [callback]
   * @return {string}
   */
  toString(callback) {
    return this.linkedList.toString(callback);
  }
}

複製代碼

應用

  1. 簡單的四則元算
import Stack from './Stack';
export default class InToPost {
  constructor() {
    this.theStack = new Stack();
    this.output = [];
  }

  /**
   * 轉換爲後綴表達式
   */
  doTrans(str) {
    this.output = [];
    for (let i = 0, len = str.length; i < len; i++) {
      const ch = str.charAt(i);
      switch (ch) {
        case '+':
        case '-':
          this.getOper(ch, 1);
          break;
        case '*':
        case '/':
          this.getOper(ch, 2);
          break;
        case '(':
          this.theStack.push(ch);
          break;
        case ')':
          this.getParen();
          break;
        default:
          this.output.push(ch);
          break;
      }
    }
    while (!this.theStack.isEmpty()) {
      this.output.push(this.theStack.pop());
    }
    return this.output;
  }

  getOper(opThis, prec1) {
    while (!this.theStack.isEmpty()) {
      const opTop = this.theStack.pop();
      if (opTop === '(') {
        this.theStack.push(opTop);
        break;
      } else {
        let prec2 = 0;
        if (opTop === '+' || opTop === '-') {
          prec2 = 1;
        } else {
          prec2 = 2;
        }
        if (prec2 < prec1) {
          this.theStack.push(opTop);
          break;
        } else {
          this.output.push(opTop);
        }
      }
    }
    this.theStack.push(opThis);
  }

  getParen() {
    while (!this.theStack.isEmpty()) {
      const chx = this.theStack.pop();
      if (chx === '(') {
        break;
      } else {
        this.output.push(chx);
      }
    }
  }

  /**
   * 計算
   */
  calculation() {
    const caStack = new Stack();
    let num1 = 0;
    let num2 = 0;
    let ans = 0;
    let ch;
    for (let i = 0, len = this.output.length; i < len; i++) {
      ch = this.output[i];
      if (ch >= '0' && ch <= '9') {
        caStack.push(parseInt(ch));
      } else {
        num2 = caStack.pop();
        num1 = caStack.pop();
        switch (ch) {
          case '+':
            ans = num1 + num2;
            break;
          case '-':
            ans = num1 - num2;
            break;
          case '*':
            ans = num1 * num2;
            break;
          case '/':
            ans = num1 / num2;
            break;
          default:
            break;
        }
        caStack.push(ans);
      }
    }
    ans = caStack.pop();
    return ans;
  }
}

複製代碼
  • 四則元算 目前僅支持10位之內計算
  1. 將中綴表達式3+2--->變爲後綴表達式32+
  • (1)從左到右逐個掃描中綴表達式中的各項,若是到達末尾則跳轉轉到(6),不然根據(2)~(5)的描述進行操做;
  • (2)遇到操做數直接輸出;
  • (3)遇到運算符(設爲a),則和棧頂的操做符(設爲b)比較優先級,若a小於等於b的優先級,則連續出棧輸出,直到a大於b的優先級或b爲(,a進棧;
  • (4)遇到(,進棧;
  • (5)遇到),則連續出棧輸出,直到遇到左括弧(爲止。其中,(出棧可是並不輸出;
  • (6)輸出棧中剩餘的操做符。
  1. 計算後綴表達式的值,遇到數字壓棧,遇到操做符取出數字計算結果,壓棧,重複此過程至循環結束,取出數據即最後結果git

  2. 分割符匹配github

import Stack from './Stack';

export default class BracketChecker {
  constructor() {
    this.stack = new Stack();
  }

  check(str) {
    let isMatch = false;
    const map = new Map([
      ['{', '}'],
      ['[', ']'],
      ['(', ')']
    ]);
    const keys = [...map.keys()];
    const values = [...map.values()];
    for (let i = 0, len = str.length; i < len; i++) {
      const ch = str.charAt(i);
      if (keys.includes(ch)) {
        this.stack.push(ch);
      } else if (values.includes(ch)) {
        if (!this.stack.isEmpty()) {
          const chx = this.stack.pop();
          // 遇到)括號出棧,並從map裏面找到)括號須要配對的(括號,相等則匹配成功
          const needKey = [...map.entries()].filter((el) => {
            return el[1] === ch;
          }).pop().shift();
          isMatch = needKey === chx;
        }
      }
    }
    return isMatch && this.stack.isEmpty();
  }
}

複製代碼

參考連接

相關文章
相關標籤/搜索