算法基础 - 栈的应用之四则运算表达式求值

计算 9 + (3-1) * 3 + 10/2
这是一个很简单的题目 我们心算也能很快得出答案
但是如果要用程序来实现 就不是很好处理了

这里面的困难就在于乘除在加减的后面 , 却要先运算, 而加入的括号之后就变得更加复杂

但仔细观察后发现, 括号都是成对出现的 有左括号就一定有右括号 , 对于多重括号最终也是可以完全嵌套匹配
这用栈结构正好合适 只要碰到左括号 ,就将此左括号进栈 而后面出现右括号时,就让栈顶的左括号出栈
期间让数字运算 这样,最终有括号的表达式从左到右巡查一遍 栈应该是由空到有元素 在到完全匹配成为空栈

但对于四则运算 ,括号也只是当中的一部分 先乘除后加减使得问题依然复杂
波兰科学家想到了一种不需要括号的后缀表达式 , 我们也把它称为逆波兰
这种后缀表达式是一种新的显示方式
我们用上面的题目来看看
正常输血表达式 9 + (3-1) * 3 + 10/2
后缀表达式 9 3 1 - 3 * + 10 2 / +
所有的符号都是在要运算的数字的后面出现

后缀表达式的计算结果

计算规则
从左到右遍历表达式的每个数字和符号 遇到数字就进栈 遇到符号就将处于栈顶的两个数字出栈 进行运算 运算结果进栈 一直到最终获得结果

  1. 初始化一个空栈 用来对要运算的数字进出使用
  2. 表达式前三个都是数字 所以 9 3 1 进栈
    此时栈为 1 3 9
  3. 接下来是 - 将 1 出栈作为减数 3 出栈作为被减数 进行运算得到结果2 进栈
    此时栈为 2 9
    4 接着是 3 进栈
    此时栈为 3 2 9
    5 后面是 * 号 将3出栈作为乘数 2 出栈作为被乘数 得到结果 6 进栈
    此时栈为 6 9
    6 接着是 + 将6 9 出栈 得到结果 15 进栈
    此时栈为 15
    7 10 2 进栈
    此时栈为 2 10 15
    8 遇见 / 2 10 出栈 得到结果5 进栈
    此时栈为 5 15
    9 最后是 + 5 15 出栈得到结果 20 进栈
    此时栈为 20

表达式结束得到结果 20

中缀表达式转后缀表达式

我们把平时所用的标准四则表达式称为 中缀表达式
中缀表达式转后缀表达式规则
从左到右遍历中缀表达式的每个数字和符号 若是数字就输出 ,即成为后缀表达式的一部分
若是符号 , 则判断其与栈顶符号的优先级 是右括号或优先级不高于栈顶符号 则栈顶元素依次出栈并输出 ,并将当前符号进栈

还是拿 9 + (3-1) * 3 + 10/2 举例

1 初始化一空栈
2 第一个数字是9 直接加入后缀表达式 接着是 + 进栈
此时栈为 + 后缀表达式 9
3 左括号 ( 进栈
此时栈为 ( + 后缀表达式 9
4 3 是数字 直接加入后缀表达式
此时栈为 ( + 后缀表达式 9 3
5 - 进栈
此时栈为 - ( + 后缀表达式 9 3
6 1 加入后缀表达式
此时栈为 - ( + 后缀表达式 9 3 1
7 ) 右括号需要去匹配 栈里的第一个左括号 并将中间符号出栈
此时栈为 + 后缀表达式 9 3 1 -
8 * 优先级高于栈顶的 + 进栈
此时栈为 * + 后缀表达式 9 3 1 -
9 3 是数字 直接出栈
此时栈为 * + 后缀表达式 9 3 1 - 3
10 + 优先级低于 栈顶的 * 并且栈里的+ 优先级也不低于当前的+ 所以 * + 出栈 + 入栈
此时栈为 + 后缀表达式 9 3 1 - 3 * +
11 10 数字 直接加入后缀表达式
此时栈为 + 后缀表达式 9 3 1 - 3 * + 10
11 / 优先级高于 栈里的 + 进栈
此时栈为 / + 后缀表达式 9 3 1 - 3 * + 10
12 2 是数字 直接加入后缀表达式
此时栈为 / + 后缀表达式 9 3 1 - 3 * + 10 2
13 中缀表达式已经到了尾部 所以将栈里元素依次出栈 加入后缀表达式
此时栈为 后缀表达式 9 3 1 - 3 * + 10 2 / +

得到最终后缀表达式 9 3 1 - 3 * + 10 2 / +

你可能感兴趣的:(算法基础 - 栈的应用之四则运算表达式求值)