中缀表达式变后缀表达式、后缀表达式(逆波兰)求值(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

  

 

 

 








               

posted @ 2017-07-18 17:28  zwxhacker  阅读(7206)  评论(1编辑  收藏  举报