前序、中序和后序表达式转换问题

前序、中序、后序表达式举例:

从这个表格中可以看到中序表达式和前序表达式、后序表达式的区别,中序表达式有括号,前序和后序没有括号。

那么为什么前序表达式和后序表达式不需要括号?答案是,这两种表达式中的运算符所对应的操作数是明确的。只有中序表达式需要额外的符号来消除歧义。前序表达式和后序表达式的运算顺序完全由运算符的位置决定。​

以A + B * C为例,操作数 A 、B 和 C 的相对位置保持不变,只有运算符改变了位置。再观察中序表达式中的运算符。从左往右看,第一个出现的运算符是 + 。但是在后序表达式中,由于 * 的优先级更高(写成完全括号表达式后乘法所在的括号先进行运算),因此 * 先于 + 出现,前序表达式与后序表达式相反。

将中序表达式转换为后序表达式的步骤如下:

(1) 创建用于保存运算符的空栈,以及一个用于保存结果的空列表。

(2) 从左往右扫描这个标记列表。

  • 如果标记是操作数,将其添加到结果列表的末尾。
  • 如果标记是左括号,将其压入栈中。
  • 如果标记是右括号,反复从栈中移除元素,直到移除对应的左括号。将从栈中
  • 取出的每一个运算符都添加到结果列表的末尾。
  • 如果标记是运算符,将其压入栈中。但是,在这之前,需要先从栈中取出优先
  • 级更高或相同的运算符,并将它们添加到结果列表的末尾。

(3) 当处理完输入表达式以后,检查栈中是否有多余的运算符。将其中所有残留的运算符全部添加到结果列表的末尾。

以A*B+C*D为例,转换后表达式为AB*CD*+:

中序表达式转换后序表达式代码如下:

首先创建栈的结构

class Stack(object):

    def __init__(self):
        self.__items = []

    def isEmpty(self):
        """检查栈是否为空"""
        return self.__items == []

    def push(self, item):
        """将一个元素添加到栈的顶端"""
        self.__items.append(item)

    def pop(self):
        """将栈顶端的元素移除"""
        return self.__items.pop()

    def peek(self):
        """返回栈顶端的元素"""
        return self.__items[len(self.__items) - 1]

    def size(self):
        """返回栈中元素的数目"""
        return len(self.__items)

转换表达式

import stack
import string

def toPostfix(symbolString):
    """中序表达式转后序表达式"""
    # 设定操作符优先级,保证乘除优先级大于加减大于括号即可
    # 不需要设‘)’的优先级,因为不会使用到
    prec = {}
    prec['/'] = 3
    prec['*'] = 3
    prec['+'] = 2
    prec['-'] = 2
    prec['('] = 1

    s = stack.Stack()
    str_list = []
    for token in symbolString:
        if token in string.ascii_uppercase:
            str_list.append(token)
        elif token == '(':
            s.push(token)
        elif token == ')':  # 找到前一个“(”匹配
            peek = s.pop()
            # 如果是操作符就直接把操作符移入列表中
            while peek != '(':
                str_list.append(peek)
                peek = s.pop()
        else:
            # 保证进入列表的优先级比栈中操作符的优先级要低
            while (not s.isEmpty()) and prec[token] <= prec[s.peek()]:
                str_list.append(peek)
            s.push(token)
    # 将剩余的栈中的操作符加入到列表中
    while not s.isEmpty():
        str_list.append(s.pop())

    return ''.join(str_list)

中序转前序表达式原理同后序是一样的,只不过在后序的基础上进行了字符串的反转

中序表达式转前序表达式步骤如下:

(1)反转输入字符串,如“(A+B)*(C+D)” 反转后为“(D+C)*(B+A)”。

(2)从字符串中取出下一个字符。

  • 如果是操作数,则直接输出。
  • 如果是“)”,压入栈中。
  • 如果是运算符但不是“(”,“)”,则不断循环进行以下处理:如果栈为空,则此运算符进栈,结束此步骤;如果栈顶是“)”,则此运算符进栈,结束此步骤;如果此运算符与栈顶优先级相同或者更高,此运算符进栈,结束此步骤;否则,运算符连续出栈,直到满足上述三个条件之一,然后此运算符进栈。
  • 如果是“(”,则运算符连续出栈,直到遇见“)”为止,将“)”出栈且丢弃之。
  • 如果还有更多的字符串,则转到第2步。
  • 如果不再有未处理的字符串了,输出栈中剩余元素。

(3)再次反转字符串得到最终结果。

中序表达式转换前序表达式代码如下:

def toPrefix(symbolString):
    """中序表达式转前序表达式"""
    prec = {}
    prec['/'] = 3
    prec['*'] = 3
    prec['+'] = 2
    prec['-'] = 2
    prec[')'] = 1

    s = stack.Stack()
    str_list = []
    symbolString = symbolString[::-1]       # 反转表达式
    for token in symbolString:
        if token in string.ascii_uppercase:
            str_list.append(token)
        elif token == ')':
            s.push(token)
        elif token == '(':  # 找到前一个“)”匹配
            peek = s.pop()
            # 如果是操作符就直接把操作符移入列表中
            while peek != ')':
                str_list.append(peek)
                peek = s.pop()
        else:
            # 保证进入列表的优先级比栈中操作符的优先级要低
            while (not s.isEmpty()) and prec[token] < prec[s.peek()]:
                str_list.append(s.pop())
            s.push(token)
    # 将剩余的栈中的操作符加入到列表中
    while not s.isEmpty():
        str_list.append(s.pop())

    return ''.join(str_list[::-1])

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值