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