• 中缀表达式变后缀表达式、后缀表达式(逆波兰)求值(python版本)


    定义:

        中缀表达式: 在通常的表达式中,二元运算符总是置于与之相关的两个运算对象之间,这种表示法也称为中缀表达式

        后缀表达式: 又叫逆波兰表达式 ,不包含括号,运算符放在两个运算对象的后面,所有的计算按运算符出现的顺序,严格从左向右进行(不再考虑运算符的优先规则,如:(2 + 1) * 3 , 即2 1 + 3 *

    一个字符串表达式s = “9 + ( 3 - 1 ) * 3 + 10 / 2”)求值的过程分为两步

    (一) 将 中缀表达式s变为后缀表达式s_after = "9 3 1 - 3 * + 10 2 / +",具体的规则如下 :

         首先维护两个空栈,(stack_exp)存放逆波兰表达式,(stack_ops)暂存操作符,运算结束后stack_ops必为空

         循环遍历字符串(将表达式分为四种元素 1、数值; 2、操作符; 3、 左括号; 4、右括号),具体情况如下

         1、遇到数值, 将该值入栈stack_exp

         2、遇到左括号, 将左括号入栈stack_ops

         3、遇到右括号,将stack_ops中的操作符从栈顶依次出栈并入栈stack_exp, 直到第一次遇到左括号终止操作(注意: 该左括号出栈stack_ops但不入栈stack_exp)至此消除表达式中的一对括号

         4、遇到四则运算操作符号(+ - * /)

              4-1、 如果stack_ops为空, 操作符入栈stack_ops

              4-2、 如果stack_ops不空,将stack_ops栈顶操作符与遍历到的操作符(op)比较:

                   4-2-1: 如果stack_ops栈顶操作符为左括或者op优先级高于栈顶操作符优先级, op入栈stack_ops,当前遍历结束

                   4-2-2: 如果op优先级小于或者等于stack_ops栈顶操作符, stack_ops栈顶操作符出栈并入栈stack_exp,重复4-1、 4-2直到op入栈stack_ops

         5、字符串遍历结束后如果stack_ops栈不为空,则依次将操作符出栈并入栈stack_exp

         python代码实现如下:

    ops_rule = {
        '+': 1,
        '-': 1,
        '*': 2,
        '/': 2
    }
    
    def middle_to_after(s):
        expression = []
        ops = []
        ss = s.split(' ')
        for item in ss:
            if item in ['+', '-', '*', '/']:
                while len(ops) >= 0:
                    if len(ops) == 0:
                        ops.append(item)
                        break
                    op = ops.pop()
                    if op == '(' or ops_rule[item] > ops_rule[op]:
                        ops.append(op)
                        ops.append(item)
                        break
                    else:
                        expression.append(op)
            elif item == '(':
                ops.append(item)
            elif item == ')':
                while len(ops) > 0:
                    op = ops.pop()
                    if op == '(':
                        break
                    else:
                        expression.append(op)
            else:
                expression.append(item)
    
        while len(ops) > 0:
            expression.append(ops.pop())
    
        return expression
    (二) 将后缀表达式s_after = "9 3 1 - 3 * + 10 2 / +" 求值,具体的规则如下 :
    初始化一个空栈stack_value,用于存放数值
    循环s_after
    1、 如果遇到数字,入栈stack_value;
    2、 如果遇到运算符, 从stack_value中依次出栈两个数(先出栈的在右, 后出栈的在左)连同遍历到的运算符组成二目运算,求值后将结果压栈stack_value
    3、 继续遍历下一个元素,直到结束
    遍历完后stack_value中的结果便是表达式的值
    python代码实现如下:
    def expression_to_value(expression):
        stack_value = []
        for item in expression:
            if item in ['+', '-', '*', '/']:
                n2 = stack_value.pop()
                n1 = stack_value.pop()
                result = cal(n1, n2, item)
                stack_value.append(result)
            else:
                stack_value.append(int(item))
        return stack_value[0]
    
    def cal(n1, n2, op):
        if op == '+':
            return n1 + n2
        if op == '-':
            return n1 - n2
        if op == '*':
            return n1 * n2
        if op == '/':
            return n1 / n2
    
    
    if __name__ == '__main__':
        expression = middle_to_after('9 + ( 3 * ( 4 - 2 ) ) * 3 + 10 / 2')
        value = expression_to_value(expression)
        print value
    
    
    

      

     
     








                   

  • 相关阅读:
    对互联网海量数据实时计算的理解 + 业界开源实时流处理系统小结 _ (技术调研参考)
    SQL语句的添加、删除、修改多种方法 —— 基本操作
    leetcode-验证二叉搜索树
    leetcode-汉明距离
    leetcode-帕斯卡三角形
    leetcode-位1的个数(位与运算)
    leetcode-打家劫舍(动态规划)
    leetcode-回文链表
    leetcode-反转链表
    leetcode-最大子序和(动态规划讲解)
  • 原文地址:https://www.cnblogs.com/wxzhao/p/7201672.html
Copyright © 2020-2023  润新知