后缀表达式

后缀表达式也叫逆波兰表达式,其求值过程可以用到栈来辅助存储。

假定待求值的后缀表达式为:9 3 1 - 3 * + 10 2 / +,则其求值过程如下:
规则 :遇见数字就压栈。碰见符号就弹栈 两个 进行运算。然后再将运算结果压栈 。依次类推

1、压栈 9 3 1 碰见 - 弹栈 1 3 运算 3-1 运算结果继续压栈 9 2 表达式剩下 3 * + 10 2 / +
下面是代码解读

/*
expression  = [9,3 ,1, -, 3, *,  +, 10, 2, /, +]
stack = []
1 数字依次压栈  压栈 9 3 1 
expression  = [ -, 3, *,  +, 10, 2, /, +]
stack = [9,3,1]
2.碰见符号弹栈 两个 进行运算 并将运算结果压栈 碰见了 - 
 弹栈  1 3 
 运算 3-1 
expression  = [  3, *,  +, 10, 2, /, +]
stack = [9,2]
依次例推
压栈 3 
expression  = [    *,  +, 10, 2, /, +]
stack = [9,2,3]
弹栈 3 2
运算 3 *2 
expression  = [  +, 10, 2, /, +]
stack = [9,6]
弹栈  6  9 
运算 9 + 6 
 expression  = [   , 10, 2, /, +]
 stack = [15]

压栈 10 2 
 expression  = [ /, +]
 stack = [15,10,2]
弹栈  2 10 
运算 10/2 
 expression  = [  +]
 stack = [15,5]
弹栈  5 15
运算 15+5 
stack = [20]
*/

上面只是说明了什么是后缀表达式的计算方法。那么后缀表达式是怎么来的呢。
还是用上面的来举例
比如说。有一个中缀表达式 9+(3-1)*3+10/5 他经过一系列的处理之后就变成了 9 3 1 - 3 * + 10 2 / +

中缀表达式转为后缀表达式 9+(3-1)*3+10/5 转 9 3 1 - 3 * + 10 5 / +

规则 :从左到右遍历中缀表达式的每个数字和符号,若是数字就输出。即成为后缀表达式的一部分。若是符号。则判断其与栈顶符号的优先级。是右括号或者优先级低于栈顶符号 (乘除优先加减)则栈顶元素依次出栈并且输出。并将当前符号进栈。一直到最终输入后缀表达式为止。

上面这段话是我从书上抄来的。是有一点难以理解。我总结了一下。如果是数字。就不用管。直接记录到后缀表达式里面 。如果是( 左括号 直接压栈,只有碰见 )右括号才可以弹出前面的一个左括号。如果是+ - 那么除过 ( 左括号 都需要依次弹出(加减乘除)。 如果是乘除。只能弹出乘除 。不能弹出比它优先级小的。

/*
expression   = [9,+,(,3,-,1,),*,3,+,10,/,5 ] 
stack = []   
suffixExpression = []  

 9 输出 后缀表达式
 expression   = [+,(,3,-,1,),*,3,+,10,/,5 ] 
 stack = []  
 suffixExpression =[9]  
 +   栈顶为空  压栈
  expression   = [ (,3,-,1,),*,3,+,10,/,5 ] 
 stack = [+ ]  
 suffixExpression =[9]  
 (   栈顶为+ 左括号优先级比+高 压栈 
 expression   = [ 3,-,1,),*,3,+,10,/,5 ] 
 stack = [+ ( ]  
 suffixExpression =[9]  
 依次类推
 expression   = [ -,1,),*,3,+,10,/,5 ] 
 stack = [+ ( ]  
 suffixExpression =[9 3 ]  

  expression   = [ 1,),*,3,+,10,/,5 ] 
 stack = [+,(,-  ]  
 suffixExpression =[9 3 ]  

  expression   = [  ),*,3,+,10,/,5 ] 
 stack = [+,(,-  ]  
 suffixExpression =[9 3  1]  
  碰见) 右括号  弹栈 一直找到左括号为止, 左右括号不进入后缀表达式中  目前 栈内 左右括号中间只有- 所以后缀表达式 追加 - 
 expression   = [  *,3,+,10,/,5 ] 
 stack = [+,  ]  
 suffixExpression =[9 3  1 -]  
 * 优先级比+高 压栈
  expression   = [   3,+,10,/,5 ] 
 stack = [+, *   ]  
 suffixExpression =[9 3  1 -]  

   expression   = [   +,10,/,5 ] 
 stack = [+, *   ]  
 suffixExpression =[9 3  1 - 3]  
 +优先级比* 低 一直弹栈直到 ( 左括号 或者栈为空 弹栈完毕之后压栈
 expression   = [  10,/,5 ] 
 stack = [+   ]  
 suffixExpression =[9 3  1 - 3 * + ]  
 
 expression   = [  /,5 ] 
 stack = [+   ]  
 suffixExpression =[9 3  1 - 3 * + 10  ]  
  expression   = [ 5 ] 
 stack = [+  /  ]  
 suffixExpression =[9 3  1 - 3 * + 10  ]  
   expression   = [ ] 
 stack = [+  /  ]  
 suffixExpression =[9 3  1 - 3 * + 10  5  ]  
 最后一个元素结束  栈内所有依次弹栈 
    expression   = [ ] 
 stack = [ ]  
 suffixExpression =[9 3  1 - 3 * + 10  5 / +  ]  
*/

明白了中缀表达式转为后缀表达式以及后缀表达式的计算规则后 可以尝试用代码来实现一下

let str = "9+(3-1)*3+10/5"
let printArr = []
let stack = [];
let mapstr = ''
arr = str.split(/[\*\(\)\+\/\-]/)
 
for (let i = 0; i < arr.length; i++) {
 
    let sy, mlen
    if (arr[i]) {
        // 数字 
        mapstr += arr[i]
        mlen = mapstr.length
        sy = str[mlen]
        printArr.push(arr[i]);
        mapstr += sy
    } else {
        // 
        mlen = mapstr.length
        sy = str[mlen]
        mapstr += sy
    }


    if (sy == "(") {
        stack.push(sy)
    }
    else if (sy == ")") {
        let item = stack.pop()
        while (item != "(") {
            printArr.push(item)
            item = stack.pop()
        }
    }
    else if (sy == "+") {
        let item = stack.pop()
        while (item) {
            if (item == "(") {
                stack.push(item)
                item = null;
            } else {
                printArr.push(item);
                item = stack.pop();
            }

        }
        stack.push(sy)
    }
    else if (sy == "-") {
        let item = stack.pop()
        while (item) {
            if (item == "(") {
                stack.push(item)
                item = null;
            }
            else {
                printArr.push(item);
                item = stack.pop();
            }
        }
        stack.push(sy)
    }
    else if (sy == "*") {
        let item = stack.pop()
        while (item) {
            if (item == "(") {
                stack.push(item)
                item = null;
            }
            else if (item == "*" || item == "/") {
                printArr.push(item);
                item = stack.pop();
            }

            else if (item == "+" || item == "-") {
                stack.push(item);
                item = null;
            }
        }
        stack.push(sy)
    }
    else if (sy == "/") {
        let item = stack.pop()
        while (item) {
            if (item == "(") {
                stack.push(item)
                item = null;
            }
            else if (item == "*" || item == "/") {
                printArr.push(item);
                item = stack.pop();
            }

            else if (item == "+" || item == "-") {
                stack.push(item);
                item = null;
            }
        }
        stack.push(sy)
    }


}
let item = stack.pop()
while (item) {
    printArr.push(item)
    item = stack.pop()
}
for (let i = 0; i < printArr.length; i++) {
    let item = printArr[i]
    if (item == "+") {
        let num2 = stack.pop() * 1
        let num1 = stack.pop() * 1
        stack.push(num1 + num2)

    }
    else if (item == "-") {
        let num2 = stack.pop() * 1
        let num1 = stack.pop() * 1
        stack.push(num1 - num2)

    }
    else if (item == "*") {
        let num2 = stack.pop() * 1
        let num1 = stack.pop() * 1
        stack.push(num1 * num2)

    }
    else if (item == "/") {
        let num2 = stack.pop() * 1
        let num1 = stack.pop() * 1
        stack.push(num1 / num2)

    }
    else {
        stack.push(item)
    }
}
 console.log(stack);  // [17] 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值