中序表达式转成前序表达式和后序表达式及其计算方法

举个例子吧:将中序表达式(23+34*45/(5+6+7))转换成后序表达式23 34 45 * 5 6 + 7 + / +

 

为什么要把它转成后序表达式呢?
      当转换成后序表达式后更方便计算表达式的值,如将后序表达式的元素依次进栈直到遇到运算符,这时候从栈中弹出两个元素,再结合运算符计算出这两个数运算的结果(如34*45=1530),将其结果压栈(此时栈元素为23 1530),然后继续将后序非符号元素压栈,直到遇到运算符。重复之前的操作!

 

如何实现该转换呢?

中序表达式转成后序表达式算法:

1)当输入的是操作数时,直接输出到后序表达式的序列中
2)当输入的是开括号时,把它压栈
3)当输入的是闭括号时,先判断栈是否为空,若为空,则发生错误并进行相关处理。若非空,把栈中元素依次弹出并输出到序列中,直到遇到第一个开括号为止,若没有遇到开括号,也即发生错误,进行相关处理
4)当输入的是运算符op(+、- 、×、/)时,有两种情况需要处理:
      a)执行循环,判断当(栈非空and栈顶不是开括号and栈顶运算符的优先级不低于输入的运算符的优先级)时,反复将栈顶元素弹出并添加到序列中
      b)否则把输入的运算符op压栈
5)当中序表达式的符号序列全部读入后,若栈内仍有元素,把它们依次弹出并放到后序表达式序列尾部。若弹出的元素遇到空括号,则说明不匹配,发生错误,并进行相关处理


再看一个例子吧:

中序表达式:2*3/(2-1)+3*(4-1)

前序表达式:+/*23-21*3-41

后序表达式:23*21-/341-*+

       中序表达式对我们而言是很直观的(我们平时接触的就是这个),但计算机处理起来比较麻烦(括号、优先级之类的),前序和后序表达式中没有括号,而且在计算中只需单向扫描,不需要考虑运算符的优先级。
  以前序表达式“+/*23-21*3-41”为例,从右往左,先取出两个操作数“1”、“4”和一个运算符“-”,计算“4-1”,将结果3回填到字符串中,现在字符串变为“+/*23-21*33”。
  再从右至左取两个数“3”、“3”和“*”,计算“3*3”,将结果“9”回填到字符串,得“+/*23-219’”,
  再取数,连续取出“9”、“1”、“2”,直到取出一个运算符“-”,将与运算符最近的两个操作数进行计算,即“2-1”得“1”,回填字符串中,现在为“+/*239”
  重复上述步骤,取出“2*3”=6,回填字符串得到“+/619”,
  再取“6/1”=6,得到“+69”,
  再取“6+9”=15。运算完毕。

       即从右至左取数,直到取出一个运算符,将刚取出的紧挨着运算符的两个操作数按运算符进行计算,结果回填至运算符。重复该步骤,直到最后只剩下一个字符串则剩下的字符串即为结果。
  后序表达式的字符串扫描方式正好和前序相反,是从左往右扫描,规则类似。


中序表达式转成前序表达式算法:

中序表达式转前序表达式步骤
1、反转输入字符串,如“2*3/(2-1)+3*(4-1)” 反转后为“ )1-4(*3+)1-2(/3*2”,
2、从字符串中取出下一个字符
  2.1.如果是操作数,则直接输出
  2.2.如果是“)”,压入栈中
  2.3.如果是运算符但不是“(”,“)”,则不断循环进行以下处理
    2.3.1.如果栈为空,则此运算符进栈,结束此步骤
    2.3.2.如果栈顶是“)”,则此运算符进栈,结束此步骤
    2.3.2.如果此运算符与栈顶优先级相同或者更高,此运算符进栈,结束此步骤
    2.3.4.否则,运算符连续出栈,直到满足上述三个条件之一,然后此运算符进栈
  2.4、如果是“(”,则运算符连续出栈,直到遇见“)”为止,将“)”出栈且丢弃之
3、如果还有更多的字符串,则转到第2步
4、不在有未处理的字符串了,输出栈中剩余元素
5、再次反转字符串得到最终结果

 

过程详细分析:

       比如说:2*3/(2-1)+3*(4-1),反转得“ )1-4(*3+)1-2(/3*2 ”;
  取第一个字符串为“)”,入栈(此时栈中为“)”);
  取下一个“1”,是操作数,直接输出(目前输出“1”);
  取下一个“-”,既不是“)”,也不是“(”,则转到2.3,此时栈顶为“)”,则该运算符进栈(栈中为“-、)”);
  取下一个“4”,直接输出(目前输出的是“14”);
  取下一个“(”,运算符连续出栈(栈中此时为“-、)”),直到遇见“)”,此时输出“-”(目前输出“14-”,栈为空);
  取下一个“*”,既不是“)”,也不是“(”,则转到2.3,进栈(栈为空);
  取下一个“3”,直接输出(目前输出“14-3”);
  取下一个“+”,此时栈顶为“*”,“+”的优先级比“*”低(2.3.4),则运算符连续出栈(只有一个*出栈,此时栈为空符合2.3.1,继续下一步),“+”进栈;
  取下一个“)”,进栈(此时栈中为“)、+”);
  取下一个“1”直接输出(目前输出为14-3*1);
  取下一个“-”,此时栈顶为“)”,“-”进栈(栈中此时为“-、)、+”);
  取下一个“2”,直接输出(目前输出“14-3*12”);
  取下一个“(”,运算符连续出栈,直到遇见“)”,此时栈中为“-、)、+”,输出-,且抛弃“)”,此时输出为“14-3*12-”,栈中为“+”;
  取下一个“/”,优先级比栈顶“+”高,此运算符进栈;
  取下一个“3”,直接输出(此时输出“14-3*12-3”);
  取下一个“*”,优先级比栈顶“+”高,此运算符进栈;
  取下一个“2”,输出(此时输出“14-3*12-32”);
  不在有未处理的运算符,输出栈中剩余元素,结果的“14-3*12-32*/+”;
  反转字符串的“+/*23-21*3-41”。

 

 

表达式求值程序实现要点::
1 、表达式求值可分为二个步骤进行,第一步先将初始表达式转换成逆波兰表示(后序序列),第二步再对逆波兰表示求表达式的值。第一阶段中要使用一个栈暂存运算符,第二阶段中要使用一个栈存放运算量,表达式的后序序列作为中间结果存放在一个队列中。

2 、顺序扫描初始表达式,当遇到运算量时,可直接将其送入输出队列中;当遇到运算符时,要与栈顶的运算符进行优先级的比较,如果前者高则进栈,如果栈顶的运算 符优先级高(或等于)可将其从栈中弹出并送入输出队列中,然后再将当前运算符入栈;当遇到左括号时即入栈,当遇到右括号时将与其配对的左括号上面的运算符 全部依次弹出送入输出队列中,再删除该左括号;当遇到‘#’时将栈中运算符全部依次弹出送入输出队列中。

3 、对逆波兰表示求表达式值的算法较为简单:从队列中取出元素,若为运算量则进栈;否则为运算符,从运算量栈中依次弹出二个运算量,运算后将结构推入栈中,重复进行直至队列为空,计算结果在栈中。

  • 6
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值