中缀表达式转后缀表达式

自从找完工作人就废了,幡然醒悟不行不行,得把忘记的都记下来。。。。。。

中缀表达式就是我们正常使用的那种,例如:a+b*c

后缀表达式就是abc*+;

为什么要有中缀表达式和后缀表达式呢?

因为中缀表达式便于人们的理解与计算,但是后缀表达式更方便计算机的运算(如二叉树、堆栈的方法计算),因此在读取一个中缀表达式后,我们得办法将他转化为后缀表达式。

转化方式有三种:

首先假设我们需要转化的中缀表达式为:

a + b * c + ( d * e + f ) * g

第一种:基于堆栈的算法

  1. 从左到右扫描每一个字符。如果扫描到的字符是操作数(如a、b等),就直接输出这些操作数。

    中缀表达式转后缀表达式

  2. 如果扫描到的字符是一个操作符,分三种情况:

    (1)如果堆栈是空的,直接将操作符存储到堆栈中(push it)

    (2)如果该操作符的优先级大于堆栈出口的操作符,就直接将操作符存储到堆栈中(push it)

    (3)如果该操作符的优先级低于堆栈出口的操作符,就将堆栈出口的操作符导出(pop it), 直到该操作符的优先级大于堆栈顶端的操作符。将扫描到的操作符导入到堆栈中(push)。

    中缀表达式转后缀表达式

    中缀表达式转后缀表达式

  3. 如果遇到的操作符是左括号"(”,就直接将该操作符输出到堆栈当中。该操作符只有在遇到右括号“)”的时候移除。这是一个特殊符号该特殊处理。

    中缀表达式转后缀表达式

    中缀表达式转后缀表达式

    中缀表达式转后缀表达式

  4. 如果扫描到的操作符是右括号“)”,将堆栈中的操作符导出(pop)到output中输出,直到遇见左括号“(”。将堆栈中的左括号移出堆栈(pop )。继续扫描下一个字符

    中缀表达式转后缀表达式

  5. 如果输入的中缀表达式已经扫描完了,但是堆栈中仍然存在操作符的时候,我们应该讲堆栈中的操作符导出并输入到output 当中。

    中缀表达式转后缀表达式

    中缀表达式转后缀表达式

第二种:括号法,这种真的很简单啊,好记又简单

      1:按照运算符的优先级对所有的运算单位加括号~

      式子变成拉:((a+(b*c))+(((d*e+f)*g))

       2:转换前缀与后缀表达式

      前缀:把运算符号移动到对应的括号前面

      则变成拉:+(+(a*(bc))*(+(*(de)+g))

      把括号去掉:++a*bc*+*de+g 前缀式子出现

      后缀:把运算符号移动到对应的括号后面

      则变成拉:((a(bc)*)+(((de)*f)+g)*)+

      把括号去掉:abc*+de*f+g *+后缀式子出现

第三种:利用语法树

      1、将式子转化为二叉树,如下所示,图做的有点丑,懒得画了,不要介意。。。。。。

中缀表达式转后缀表达式

      2、通过后序遍历将其写出来,即可得到结果:abc*+de*f+g *+

在这里补充一点,如何将表达式变成二叉树:

表达式生成树的特点为:

    a. 叶子节点都是操作数;

    b. 非叶子节点都是运算符;

    c. 树根的运算符优先级低;

步骤如下

找到表达式中优先级最低的运算符作为树根(注意括号会提升内部的优先级),并将原表达式分解成左右两个表达式;

分别对左右表达式做步骤1, 左边生成的树为树根的左子树,右边生成的树为树根的右子树;

重复步骤1,2, 直到分解的表达式里没有运算符(只剩下数字)为止;

注意一点:在遇到像本式中a后面的+号和c后面的+的优先级问题,在正常计算时a后面的+会先使用所以他的优先级比c后面的+优先级高。所以能得到上面的二叉树。

后序遍历的问题看我其他的文章中有介绍。