栈的应用:中缀表达式和后缀表达式互转

一、概要

       中缀表达式是我们经常接触的算术表达式,如(a+b)* c,a * (c - d)等,优点是便于记忆,缺点是对运算顺序有严格的要求。后缀表达式又称逆波兰式,如abc*+d e *f+g*+,虽然不便记忆,但是它不像中缀表达式,对于运算的顺序是没有要求,可以按照顺序扫描的方法计算表达式,因此在计算机内部容易用编程的方式实现表达式的求值。

 

二、中缀转后缀

# !/usr/bin/python
# coding=utf-8

# 中缀表达式转后缀表达式
# input:  中缀表达式
# output: 后缀表达式
def infix_to_suffix(inf):
    stack = []
    suf = ""
    pt = i = -1
    slen = len(inf) - 1
    # {"operator" : "priority"}
    opt_dict = {"(":3, ")":3, "+":1, "-":1, "*":2, "/":2}
    while i < slen:
        i += 1
        char = inf[i]
        if char not in opt_dict.keys():
            suf += char.strip()
            continue
        # pop element util find '(' which should also be pop from stack
        if char == ")":
            while pt >= 0:
                if stack[pt] == "(":
                    del stack[pt]
                    pt = pt - 1
                    break
                suf += stack[pt]
                del stack[pt]
                pt = pt - 1
            continue
        # pop element whose level less than pri (priority)
        # obviously, if is '(', 'break' make effect instantly
        pri = opt_dict[char]
        while pt >= 0:
            if opt_dict[stack[pt]] < pri or stack[pt] == '(':
                break
            suf += stack[pt]
            del stack[pt]
            pt = pt - 1
        stack.append(char.strip())
        pt += 1
    # output remainder of stack if possible
    suf += "".join(stack)
    return suf

def main():
    inf = "a+b*c+(d*e+f)*g"
    #inf = "a+b*c+(d*e+f)"
    #inf = "(a+b)*(c*(d+e))"
    suf = infix_to_suffix(inf)
    print(suf)

if __name__ == '__main__':
    main()

    几点说明

  1.   stack是一个列表,用来模拟栈,pt 指示栈顶;
  2.   不同运算符的优先级不同,相应的操作亦不同,详见注释;
  3.    suf 表示最终输出的后缀表达式;
  4.    跳过空格,所以需要调用strip();
  5.    为方便起见,仅将“+,-,*,/”四种运算符和“()”考虑在内;

 

三、后缀转中缀

      后缀转中缀相对比较简单。大致过程为:初始化一个空栈,然后顺序扫描表达式,如果不是运算符则压栈,否则从栈中相继弹出两个元素通过运算符做运算,并将运算后的表达式压栈。

# !/usr/bin/python
# coding=utf-8

# 后缀转中缀
# input: 后缀表达式
# output: 中缀表达式
def suffix_to_infix(suf):
    opt_lst = ['+','-','*','/']
    i = p = -1
    explen = len(exp) - 1
    stack = []
    while i < explen:
      i += 1
      if exp[i] == ' ':
          continue
      if exp[i] in opt_lst:
          # pop stack[p] and stack[p-1]
          e1 = stack[p]
          del stack[p]
          p = p - 1
          e2 = stack[p]
          del stack[p]
          p = p - 1
          if exp[i] == "+" or exp[i] == "-":
              e = str("(" + e2 + exp[i] + e1 + ")")
          else:
              e = str(e2 + exp[i] + e1)
          p += 1
          stack.append(e)
      else:
          # push to stack top
          stack.append(exp[i])
          p += 1
    return stack[0]

def main():
    #suf = "ab+cde+**"
    suf = "abc*+de*f+g*+"
    inf = suffix_to_infix(suf)
    print(inf)

if __name__ == '__main__':
    main()

    说明:当发现“+,-”运算符时,对弹出的两个元素做运算后需要加上"()",这是为了保持原有的中缀表达式的运算优先级。可能会加一些多于的"()",但是运算不至于出错,此处可以优化,只是为了演示栈的应用没有实现。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
中缀表达式后缀表达式是一种常用的算法问题。中缀表达式是我们常见的数学表达式形式,例如(3 + 4) * 5 - 6,而后缀表达式(也叫逆波兰表达式)则是将操作符放在操作数之后的表达式形式,例如3 4 + 5 * 6 -。 进行中缀表达式后缀表达式的算法可以使用来实现。具体步骤如下: 1. 创建一个空和一个空列表,用于存储操作符和最终的后缀表达式; 2. 从左到右遍历中缀表达式的每个字符; 3. 如果当前字符是数字或字母,则将其添加到后缀表达式的列表中; 4. 如果当前字符是左括号,则将其压入中; 5. 如果当前字符是右括号,则将中的操作符依次弹出并添加到后缀表达式的列表中,直到遇到左括号为止; 6. 如果当前字符是操作符,则判断顶操作符的优先级,如果顶操作符的优先级高于等于当前操作符,则将顶操作符弹出并添加到后缀表达式的列表中,重复这一步骤直到顶操作符的优先级低于当前操作符或为空,最后将当前操作符压入中; 7. 遍历完中缀表达式后,将中的操作符依次弹出并添加到后缀表达式的列表中; 8. 最终得到的列表即为转换后的后缀表达式。 以中缀表达式(3 + 4) * 5 - 6为例,按照上述算法进行转换得到后缀表达式3 4 + 5 * 6 -。 通过这个算法,我们可以将中缀表达式转换为后缀表达式,这种形式更适合计算机进行解析和计算。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值