javascript之使用逆波蘭表達式(後綴表達式)實現算數表達式計算

javascript之使用逆波蘭表達式(後綴表達式)實現算數表達式計算

使用jexl庫

const jexl = require('jexl');
// addBinaryOp 添加二元運算或者修改
// 可以根據jexl的lib/grammar.js裏面的優先級來決定執行順序
jexl.addBinaryOp('|', 40, (left, right) => {
    return left * right;
});
console.log(jexl.evalSync('2|3+4'))


(1)npm-jexl庫參考
(2)github源碼

知識點

  1. 逆波蘭表達式(後綴表達式)
    :具體逆波蘭表達式相關介紹可參考

使用JavaScript實現

1.定義棧

class Stack {
    constructor() {
      this._items = []; // 儲存數據
    }
    // 向棧內壓入一個元素
    push(item) {
      this._items.push(item);
    }
    // 把棧頂元素彈出
    pop() {
      return this._items.pop();
    }
    // 返回棧頂元素
    peek() {
      return this._items[this._items.length - 1];
    }
    // 判斷棧是否爲空
    isEmpty() {
      return !this._items.length;
    }
    // 棧元素個數
    size() {
      return this._items.length;
    }
    // 清空棧
    clear() {
      this._items = [];
    }
}

2.將普通的算數表達式(中綴表達式)轉換爲逆波蘭表達式(後綴表達式)

// 將普通算數表達式即中綴表達式轉換爲逆波蘭表達式即後綴表達式
function rp(str) {
    var arr = str.split('');
    var ops = '+-#*/'.split(''); // #用來分級,+-是同一級,*/同一級,兩級之間的位置差至少爲2
    var result = [], temp = [];
    arr.forEach(function(ele, ind) {
        if (ele == '(') {
            temp.push(ele); // 左括號直接推入暫存區
        } else if (ele == ')') {
            var flag = true;
            while (flag) {
                if (temp[temp.length-1] != '(') {
                    result.push(temp.pop())
                } else {
                    temp.pop();
                    flag = false;
                }
            }
        } else if (ops.indexOf(ele) != -1) {
            cb(ele, temp)
            function cb(x, o) {
                if (o.length == 0 || o[o.length-1] == '(' || 
                    ops.indexOf(x) - ops.indexOf(o[o.length-1]) > 2) { //判斷分級
                    o.push(x)
                }  else {
                    result.push(o.pop());
                    return cb(x, o)
                }
            }
        } else {
            result.push(ele);
        }
    })
    while (temp.length > 0) {
        if(temp[temp.length-1] != '(') {
            result.push(temp.pop())
        } else {
            temp.pop()
        }
    }
    return result;
}

3.計算逆波蘭表達式

function isOperator(str) {
    return ['+', '-', '*', '/'].includes(str);
}
// 逆波蘭表達式計算
function clacExp(exp) {
    const stack = new Stack();
    for (let i = 0; i < exp.length; i++) {
      const one = exp[i];
      if (isOperator(one)) {
        const operatNum1 = stack.pop();
        const operatNum2 = stack.pop();
        const expStr = `${operatNum2}${one}${operatNum1}`;
        const res = eval(expStr);
        stack.push(res);
      } else {
        stack.push(one);
      }
    }
    return stack.peek();
}

測試

const arr = rp('(2*(3+4)+1)*4');
const result = clacExp(arr);
console.log(result); // 60
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章