当前位置:   article > 正文

中缀表达式 转换为 前缀 后缀表达式_python 中缀表达式转换成前缀表达式

python 中缀表达式转换成前缀表达式

中缀转后缀表达式

考虑表达式 A + B * CA B C * +是等价的后缀表达式。 我们已经注意到,操作数 A,B 和 C 保持在它们的相对位置。只有操作符改变位置。再看中缀表达式中的运算符。从左到右出现的第一个运算符为 +。 然而,在后缀表达式中,+ 在结束位置,因为下一个运算符 * 的优先级高于加法。 原始表达式中的运算符的顺序在生成的后缀表达式中相反。

当我们处理表达式时,操作符必须保存在某处,因为它们相应的右操作数还没有看到。 此外,这些保存的操作符的顺序可能由于它们的优先级而需要反转。这是在该示例中的加法和乘法的情况,由于加法运算符在乘法运算符之前,并且具有较低的优先级,因此需要在使用乘法运算符之后出现。 由于这种顺序的反转,考虑使用栈来保存运算符直到用到它们是有意义的。

(A + B)* C的情况会是什么样呢? 回想一下,A B + C *是等价的后缀表达式。从左到右处理此中缀表达式,我们先看到 +。 在这种情况下,当我们看到 *+已经放置在结果表达式中,由于括号它的优先级高于*。 我们现在可以开始看看转换算法如何工作。当我们看到左括号时,我们保存它,表示高优先级的另一个运算符将出现。该操作符需要等到相应的右括号出现以表示其位置(回忆完全括号的算法)。 当右括号出现时,可以从栈中弹出操作符。

当我们从左到右扫描中缀表达式时,我们将使用栈来保留运算符。这将提供我们在第一个例子中注意到的反转。 堆栈的顶部将始终是最近保存的运算符。每当我们读取一个新的运算符时,我们需要考虑该运算符如何与已经在栈上的运算符(如果有的话)比较优先级。

假设中缀表达式是一个由空格分隔的标记字符串。 操作符标记是*,/,+- ,以及左右括号。操作数是单字符 A,B,C 等。 以下步骤将后缀顺序生成一个字符串。

  1. 创建一个名为 opstack 的空栈以保存运算符。给输出创建一个空列表。
  2. 通过使用字符串方法拆分将输入的中缀字符串转换为标记列表。
  3. 从左到右扫描标记列表。
    • 如果标记是操作数,将其附加到输出列表的末尾。
    • 如果标记是左括号,将其压到 opstack 上。
    • 如果标记是右括号,则弹出 opstack,直到删除相应的左括号。将每个运算符附加到输出列表的末尾。
    • 如果标记是运算符,*,/,+- ,将其压入 opstack。但是,首先删除已经在 opstack 中具有更高或相等优先级的任何运算符,并将它们加到输出列表中。
  4. 当输入表达式被完全处理时,检查 opstack。仍然在栈上的任何运算符都可以删除并加到输出列表的末尾。

Figure 展示了对表达式 A * B + C * D 的转换算法。注意,第一个 * 在看到 + 运算符时被删除。另外,当第二个 * 出现时, + 保留在栈中,因为乘法优先级高于加法。在中缀表达式的末尾,栈被弹出两次,删除两个运算符,并将 + 作为后缀表达式中的最后一个运算符。

3.9.中缀后缀和后缀表达式.figure9]![

Figure

为了在 Python 中编写算法,我们使用一个名为 prec 的字典来保存操作符的优先级。这个字典将每个运算符映射到一个整数,可以与其他运算符的优先级(我们使用整数3,2和1)进行比较。左括号将赋予最低的值。这样,与其进行比较的任何运算符将具有更高的优先级,将被放置在它的顶部。第15行将操作数定义为任何大写字符或数字。完整的转换函数见 ActiveCode 1。

from pythonds.basic.stack import Stack

def infixToPostfix(infixexpr):
    prec = {}
    prec["*"] = 3
    prec["/"] = 3
    prec["+"] = 2
    prec["-"] = 2
    prec["("] = 1
    opStack = Stack()
    postfixList = []
    tokenList = infixexpr.split()

    for token in tokenList:
        if token in "ABCDEFGHIJKLMNOPQRSTUVWXYZ" or token in "0123456789":
            postfixList.append(token)
        elif token == '(':
            opStack.push(token)
        elif token == ')':
            topToken = opStack.pop()
            while topToken != '(':
                postfixList.append(topToken)
                topToken = opStack.pop()
        else:
            while (not opStack.isEmpty()) and \
               (prec[opStack.peek()] >= prec[token]):
                  postfixList.append(opStack.pop())
            opStack.push(token)

    while not opStack.isEmpty():
        postfixList.append(opStack.pop())
    return " ".join(postfixList)

print(infixToPostfix("A * B + C * D"))
print(infixToPostfix("( A + B ) * C - ( D - E ) * ( F + G )"))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

执行结果如下

>>> infixtopostfix("( A + B ) * ( C + D )")
'A B + C D + *'
>>> infixtopostfix("( A + B ) * C")
'A B + C *'
>>> infixtopostfix("A + B * C")
'A B C * +'
>>>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

中缀转前缀表达式

首先构造一个运算符栈,然后从右至左扫描中缀表达式。如果是操作数,则直接输出,作为前缀表达式的一个直接转换表达式Temp(最后,前缀表达式由该表达式翻转得到);如果是运算符,则比较优先级:若该运算符优先级大于等于栈顶元素,则将该运算符入栈,否则栈内元素出栈并加到Temp表达式尾端,直到该运算符大于等于栈顶元素的优先级时,再将该运算符压入栈中。遇到右括号直接压入栈中,如果遇到一个左括号,那么就将栈元素弹出并加到Temp表达式尾端,但左右括号并不输出。最后,若运算符栈中还有元素,则将元素一次弹出并加到Temp表达式尾端,最后一步是将Temp表达式翻转。

假定有中缀表达式1 + (( 2 + 3)* 4 ) – 5

其过程如下图所示:

和转为后缀不同之处在于:

  • 从右向左读,第一个reverse
  • 最后还要再reverse一下
  • 栈中的元素的优先级必须大于表达式中的元素才能出栈,后缀是大于等于
  • 加入栈中的是),因为是从右向左扫
def midTopost(expr):
    prec={}
    prec["*"] = 3
    prec["/"] = 3
    prec["+"] = 2
    prec["-"] = 2
    prec["("] = 1

    opstack = Stack() # 用于保存符号
    postfixList = [] # 保存最终的表达式


    tokenList = expr.split()
    tokenList.reverse()
    for token in tokenList:
        if token in  "ABCDEFGHIJKLMNOPQRSTUVWXYZ" or token in "0123456789":
            postfixList.append(token)
        elif token == ')':
            opstack.push(token)
        elif token == '(':
            topToken = opstack.pop()
            while topToken != '(':
                postfixList.append(topToken)
                topToken = opstack.pop()
        else:
            while (not opstack.isEmpty()) and (prec[opstack.peek()] > prec[token]):
                postfixList.append(opstack.pop())
            opstack.push(token)


    while not opstack.isEmpty():
        postfixList.append(opstack.pop())

    postfixList.reverse()
    return " ".join(postfixList)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/503544
推荐阅读
相关标签
  

闽ICP备14008679号