|
3.2.4 表达式求值问题
如何由原表达式转换成后缀式?
先分析一下"原表达式"和"后缀式"两者中运算符出现的次序有什么不同。
例一
原表达式:
后缀式:
例二
原表达式:
后缀式:
|
|
从这两个例子的结果你有没有看出什么名堂来?为什么在例一的后缀式中运算符出现的先后次序和原表达式中是相同的?而同样这几个运算,在例二的后缀式中运算符出现的次序就和原表达式中的不同呢? |
|
|
例一原表达式中运算符出现的先后次序恰为运算的顺序,自然在后缀式中它们出现的次序和原表达式相同。但例二中运算符出现的先后次序不应该是它的运算顺序。按照算术运算规则,先出现的"加法"应在在它之后出现的"乘法"完成之后进行,而应该在后面出现的"减法"之前进行;同理,后面一个"乘法"应后于在它之前出现的"除法"进行,而先于在它之前的"减法"进行。
这可能有点绕嘴,为此我们先引进一个运算符的"优先数"的概念。给每个运算符赋以一个优先数的值,如下所列:
运算符
优先数
其"**"为乘幂运算,"#"为结束符。容易看出,优先数反映了算术运算中的优先关系,即优先数"高"的运算符应优先于优先数低的运算符进行运算。
也就是说,对原表达式中出现的每一个运算符是否即刻进行运算取决于在它后面出现的运算符,如果它的优先数"高或等于"后面的运算,则它的运算先进行,否则就得等待在它之后出现的所有优先数高于它的"运算"都完成之后再进行。
显然,保存运算符的结构应该是个栈,从栈底到栈顶的运算符的优先数是从低到高的,因此它们运算的先后应是从栈顶到栈底的。
|
|
|
|
|
因此,从原表达式求得后缀式的规则为:
1) 设立运算符栈;
2) 设表达式的结束符为"#",预设运算符栈的栈底为"#";
3) 若当前字符是操作数,则直接发送给后缀式;
4) 若当前字符为运算符且优先数大于栈顶运算符,则进栈,否则退出栈顶运算符发送给后缀式;
5) 若当前字符是结束符,则自栈顶至栈底依次将栈中所有运算符发送给后缀式;
6) "("对它之前后的运算符起隔离作用,则若当前运算符为"("时进栈;
7) ")"可视为自相应左括弧开始的表达式的结束符,则从栈顶起,依次退出栈顶运算符发送给后缀式直至栈顶字符为"("止。
|
|
|
|