中缀表达式转后缀表达式


1、中缀表达式和后缀表达式

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

后缀表达式就是abc*+;

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

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

2、中缀表达式转后缀表达式

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

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

其转换成后缀表达式则为 a b c * + d e * f  + g * +

2.1 基于堆栈的方法

转换过程需要用到栈,具体过程如下:

1、从左到右扫描每一个字符,如果遇到操作数,我们就直接将其输出。

2、如果遇到操作符,有如下几种情况

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

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

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

    • 优先级  "()" >  "*/"  > "+-"
    • 只有在遇到" ) "的情况下我们才弹出" ( ",其他情况我们都不会弹出" ( "。这一点根据优先级也很好理解,括号的优先级最高

4)如果遇到一个右括号,则将栈元素弹出,将弹出的操作符输出直到遇到左括号为止。注意,左括号只弹出并不输出

3、如果我们读到了输入的末尾,则将栈中所有元素依次弹出。

图解过程如下:

1、从左到右扫描每一个字符,如果遇到操作数,我们就直接将其输出。

2、如果遇到操作符,有如下几种情况

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

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

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

遇到『+』号,当前栈中的元素为『*, +』,优先级都不低于当前操作符『+』,故先弹出,『+』再入栈

 遇到『(』号,优先级最高,『(』直接入栈,操作数直接输出

遇到『*』号,优先级高,『(』是栈顶元素,因此直接入栈,操作数直接输出

遇到『+』号,优先级低,『*』是栈顶元素,先出栈,『+』再入栈,操作数直接输出 

 4)如果遇到一个右括号,则将栈元素弹出,将弹出的操作符输出直到遇到左括号为止。注意,左括号只弹出并不输出 

 

『*』入栈,操作数输出

3、如果我们读到了输入的末尾,则将栈中所有元素依次弹出。 

2.2 括号法

好记又简单,转换过程如下

1、根据运算符的优先级对中缀表达式加括号(有几个运算符就有几对括号)(原本有的括号不用加)

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

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

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

        则变成:+ ( + ( a * ( b c) ) * ( + ( * ( d e ) f ) g ) )

        把括号去掉:+ + a * b c * + * d e f g 即为前缀表达式

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

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

        把括号去掉:abc*+de*f+g *+  即为后缀表达式