中缀转前缀(后缀)表达式,前缀(后缀)表达式求值

中缀转前缀

eg: (3+5)*7

我们按照如下步骤将其转换为前缀表达式:
由于前缀表达式要求运算符在操作数之前,所以必须从后向前扫描中缀表达式
定义prefix=[]

  • 扫描到7,一个操作数什么也干不了,所以prefix=[7]
  • 扫描到*,此时什么也干不了,先记住*号
  • 扫描到5,5和7之间由于有括号,不能算乘法,所以prefix=[5,7]
  • 扫描到+,由于括号的存在,此时什么也干不了,记住+号
  • 扫描到3,由于3和5可以算加法,所以prefix=[+,3,5,7]
  • 由于3+5的结果可以和7算乘法,所以prefix=[*,+,3,5,7]

中缀转后缀

eg: (3+5)*7

我们按照如下步骤将其转换为后缀表达式:
由于后缀表达式要求运算符在操作数之后,所以必须从前向后扫描中缀表达式
定义suffix=[]

  • 扫描到3,一个操作数什么也干不了,所以suffix=[3]
  • 扫描到+,此时什么也干不了,先记住+号
  • 扫描到5,5和3之间可以算加法,所以suffix=[3,5,+]
  • 扫描到*,此时什么也干不了,记住*号
  • 扫描到7,由于3和5的结果可以和7算乘法,所以suffix=[3,5,+,7,*]

利用栈实现中缀转前缀

定义两个栈,一个是运算符栈,一个是操作数栈。
从后向前扫描中缀表达式

  • 如果是操作数,直接push到操作数栈
  • 如果是右括号,例如:)]},直接push到运算符栈
  • 如果是左括号,那么运算符栈中一定在对应的右括号直到栈顶元素之间包含着运算符,此时一直pop运算符栈(弹出的运算符放到操作数栈中),直到遇到对应的右括号为止,此时就可以消除这一对括号
  • 如果是运算符,那么需要比较它和栈顶元素的优先级。如果栈顶元素的优先级大,那么说明此时形如1+2*3,此时栈顶元素是*,那么由于2和3之间可以算乘法,所以直接弹出栈顶元素,然后把+号入栈。这个操作一直执行到栈顶元素的优先级小于当前运算符的优先级。(需要注意的是如果栈顶元素是右括号,那么不能弹栈,因为右括号要等到对应的左括号才能弹栈)
  • 重复上面的步骤,直到扫描到中缀表达式的第一个token
def infix_to_prefix(expression):
    #eg ['(', '3', '+', '5', ')', '*', '7']
    operator_stack=[]#运算符栈
    operand_stack=[]#操作数栈
    operator_priority={'+':0,'-':0,'*':1,'/':1}
    
    expression=expression[:]
    expression.reverse()#转前缀的过程是从右至左扫描
    #['7', '*', ')', '5', '+', '3', '(']
    for e in expression:
        if e==')':
            operator_stack.append(e)
        elif e=='(':
            #operator_stack中的')'直到栈顶元素要全部弹出来
            temp=operator_stack.pop()
            while temp!=')':
                operand_stack.append(temp)
                temp=operator_stack.pop()
        elif e in operator_priority:
            #此时e是运算符,需要比较栈顶元素的优先级
            while len(operator_stack)!= 0 and operator_stack[-1]!=')' and operator_priority[e]<operator_priority[operator_stack[-1]]:
                operand_stack.append(operator_stack.pop())
            operator_stack.append(e)
        else:
            operand_stack.append(e)
    while len(operator_stack)!=0:
        operand_stack.append(operator_stack.pop())
    
    operand_stack.reverse()
    return operand_stack

在这里插入图片描述

利用栈实现中缀转后缀

定义两个栈,一个是运算符栈,一个是操作数栈。
从前向后扫描中缀表达式

  • 如果是操作数,直接push到操作数栈
  • 如果是左括号,例如:(,直接push到运算符栈
  • 如果是右括号,那么运算符栈中一定在对应的左括号直到栈顶元素之间包含着运算符,此时一直pop运算符栈(弹出的运算符放到操作数栈中),直到遇到对应的左括号为止,此时就可以消除这一对括号
  • 如果是运算符,那么需要比较它和栈顶元素的优先级。如果栈顶元素的优先级大,那么说明此时形如2*3+1,此时栈顶元素是*,那么由于2和3之间可以算乘法,所以直接弹出栈顶元素,然后把+号入栈。这个操作一直执行到栈顶元素的优先级小于当前运算符的优先级。(需要注意的是如果栈顶元素是左括号,那么不能弹栈,因为左括号要等到对应的右括号才能弹栈)
  • 重复上面的步骤,直到扫描到中缀表达式的最后一个token
def infix_to_suffix(expression):
    #eg ['(', '3', '+', '5', ')', '*', '7']
    operator_stack=[]#运算符栈
    operand_stack=[]#操作数栈
    operator_priority={'+':0,'-':0,'*':1,'/':1}
    expression=expression[:]
    for e in expression:
        if e=='(':
            operator_stack.append(e)
        elif e==')':
            temp=operator_stack.pop()
            while temp!='(':
                operand_stack.append(temp)
                temp=operator_stack.pop()
        elif e in operator_priority:
            while len(operator_stack)!=0 and operator_stack[-1]!='(' and operator_priority[e]<operator_priority[operator_stack[-1]]:
                operand_stack.append(operator_stack.pop())
            operator_stack.append(e)
        else:
            operand_stack.append(e)
    
    while len(operator_stack)!=0:
        operand_stack.append(operator_stack.pop())
    return operand_stack

在这里插入图片描述

根据前缀表达式求值

思路很简单,从后向前扫描前缀表达式,遇到操作数进栈,遇到运算符就弹出两个元素计算,计算的结果再次push进栈中

def compute_prefix_expression(prefix_expression):
    
    stack=[]
    operators=['+','-','*','/']
    prefix_expression=prefix_expression[:]
    prefix_expression.reverse()
    for e in prefix_expression:
        if e not in operators:
            stack.append(e)
        else:
            assert len(stack)>=2
            operand_right=stack.pop()
            operand_left=stack.pop()
            res=eval(operand_left+e+operand_right)
            stack.append(str(res))
    assert len(stack)==1
    return stack.pop()

在这里插入图片描述

根据后缀表达式求值

思路很简单,从前向后扫描后缀表达式,遇到操作数进栈,遇到运算符就弹出两个元素计算,计算的结果再次push进栈中

def compute_suffix_expression(suffix_expression):
    
    stack=[]
    operators=['+','-','*','/']
    suffix_expression=suffix_expression[:]
    for e in suffix_expression:
        if e not in operators:
            stack.append(e)
        else:
            assert len(stack)>=2
            operand_right=stack.pop()
            operand_left=stack.pop()
            res=eval(operand_left+e+operand_right)
            stack.append(str(res))
    assert len(stack)==1
    return stack.pop()

在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
中缀表达式是我们常见的数学表达式的一种写法,它是以操作符位于操作数的两侧的形式来示计算顺序。而前缀表达式后缀表达式中缀表达式的另外两种等价的写法。 将中缀表达式换为前缀表达式的方法如下: 1. 从右到左遍历中缀表达式的每个字符。 2. 如果字符是操作数,直接输出到前缀表达式。 3. 如果字符是操作符,有两种情况: - 如果操作符的优先级比栈顶操作符的优先级高,将操作符入栈。 - 如果操作符的优先级比栈顶操作符的优先级低或相等,弹出栈顶操作符,并将弹出的操作符和操作数组合为一个前缀表达式,再将该前缀表达式入栈。 4. 当遍历完中缀表达式后,将栈中的操作符依次弹出,并将每个弹出的操作符和操作数组合为一个前缀表达式,再将该前缀表达式入栈。 5. 最后得到的栈顶即为换后的前缀表达式。 将中缀表达式换为后缀表达式的方法基本相同,只需将步骤3中操作符的优先级比较符号调整为"低或相等"即可。 中缀表达式后缀表达式的方法如下: 1. 从左到右遍历中缀表达式的每个字符。 2. 如果字符是操作数,直接输出到后缀表达式。 3. 如果字符是操作符,有两种情况: - 如果操作符的优先级比栈顶操作符的优先级高或栈为空,将操作符入栈。 - 如果操作符的优先级比栈顶操作符的优先级低或相等,弹出栈顶操作符,并将弹出的操作符和操作数组合为一个后缀表达式,再将该后缀表达式入栈。 4. 当遍历完中缀表达式后,将栈中的操作符依次弹出,并将每个弹出的操作符和操作数组合为一个后缀表达式,再将该后缀表达式入栈。 5. 最后得到的栈顶即为换后的后缀表达式。 通过上述步骤,我们可以将中缀表达式换为前缀后缀表达式
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值