栈实现中缀转后缀,并用逆波兰方式计算

stack.js

class Stack {
    constructor(){
        // dataStore 保存所有数据
        this.dataStore=[];
        // top 指示可以添加数据的“位置”
        this.top=0;
    }
    // 当然定义栈自己的push 方法,并让顶指针加一
    push(elem){
        this.dataStore[this.top++]=elem;
    }
    // 返回最顶部的值
    peek(){
        return this.dataStore[this.top-1]
    }
    // 出栈一个元素,即最顶部的值。并让指针减一,注意是先用后减
    pop(){
        return this.dataStore[--this.top]
    }
    // 因为无论添加值、访问值、还是出栈值,都是根据this.top
    // 就像数组清空,直接令length=0
    clear(){
        this.top=0
    }
    length(){
        return this.top;
    }
}

中缀转后缀

const Stack = require('./stack.js')

/**
 * 传入一个字符串类型的计算式
 * @param {*} op 
 */
function converted(op) {
    // 符号先入栈s1;数字直接入栈s2
    const s1 = new Stack();
    const s2 = new Stack();
    let nums = '';      // 方便入栈完整数字
    for (let i = 0; i < op.length; i++) {
        switch (op[i]) {
            // 实现圆括号。方括号、大括号类似
            case '(': s1.push(op[i]); break;
            // 遇到后括号,将s1栈顶至前括号"("之间的所有运算符依次入栈 s2,然后扔掉"("
            case ')':
                while (s1.peek() != '(') {
                    s2.push(s1.pop())
                }
                s1.pop();
                break;
            case '+':
            case '-':
                while (s1.top != 0 && s1.peek()!='(') {
                    s2.push(s1.pop())
                }
                s1.push(op[i])
                break;
            case '*':
            case '/':
                s1.push(op[i]);
                break;
            default:
                // 入栈完整数字
                while ('0' <= op[i] && op[i] <= '9' || str[i] == '.') {
                    nums += op[i];
                    i++;
                }
                s2.push(nums);
                i -= 1;
                nums = '';
        }
    }
    // 最后将s1栈中剩下的所有运算符都入栈s2
    while (s1.length() > 0) {
        s2.push(s1.pop())
    }
    return s2;
}

let s1=converted(op)

/**
 * 注意,s2 栈中从底至顶排列就是中缀转后缀的表达式
 * 在s2倒序,才能够用逆波兰的方式计算
 * @param {*} s 
 */
function reverse(s){
    const s1=new Stack();
    while(s.length()>0){
        s1.push(s.pop())
    }
    return s1;
}

let s2=reverse(s1);

function operator(s2){
    const s1=new Stack();
    while(s2.length()>0){
        let temp=s2.pop();
        // 在s2中每次弹出一个元素,判断该元素的类型
        // 注意,每一个元素都是字符串类型,因此用isNaN 方法判断 
        if(isNaN(temp)){
            const t1=Number(s1.pop())
            const t2=Number(s1.pop())
            switch(temp){
                case '+':s1.push(t2+t1);break;
                case '-':s1.push(t2-t1);break;
                case '*':s1.push(t2*t1);break;
                case '/':s1.push(t2/t1);break;
                default :return ;
            }
        }else {
            s1.push(temp)
        }
    }
    // s1 栈的最后一个值即为计算式结果
    return s1.pop();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值