将Postfix Python代码转换为前缀

时间:2016-02-15 22:48:39

标签: python stack postfix-notation prefix-operator

我正在从interactivepython.org学习Python。在这个site上,他们有用于评估后缀表达式的代码..但我想看看如何对前缀表达式进行处理。这是代码:

def postfixEval(postfixExpr):
    operandStack = Stack()
    tokenList = postfixExpr.split()

    for token in tokenList:
        if token in "0123456789":
            operandStack.push(int(token))
        else:
            operand2 = operandStack.pop()
            operand1 = operandStack.pop()
            result = doMath(token,operand1,operand2)
            operandStack.push(result)
    return operandStack.pop()

def doMath(op, op1, op2):
    if op == "*":
        return op1 * op2
    elif op == "/":
        return op1 / op2
    elif op == "+":
        return op1 + op2
    else:
        return op1 - op2

print(postfixEval('7 8 + 3 2 + /'))

如果我正确理解了这一课,我会改变操作数排序吗?

2 个答案:

答案 0 :(得分:0)

不,操作数的顺序相同。不同之处在于您必须在操作数之前执行操作,而不是之后操作。这很复杂,因为您可能必须进行递归调用来评估操作数:如果操作数以操作开头,则会重复。

答案 1 :(得分:0)

您可以为前缀表示法算法编写类似的解析器,但它会更复杂,因为当您收到数字令牌时要做的事情的逻辑更复杂(有时您存储它,有时您评估一个运算符并存储结果或评估另一个运算符等)。使用递归通常更容易,因为函数调用堆栈可以比您必须手动管理的堆栈更容易处理它。

这是一个使用递归的实现(以及一个将标记作为流处理的迭代器):

def prefix_eval(prefix_expr):
    return prefix_eval_rec(iter(prefix_expr.split()))

def prefix_eval_rec(expr_iter):
    token = next(expr_iter)
    if token.isdigit():
        return int(token)

    op1 = prefix_eval_rec(prefix_iter)
    op2 = prefix_eval_rec(prefix_iter)
    return doMath(token, op1, op2)

这是一个没有递归的快速尝试。这比后缀代码要麻烦得多,因为我们需要知道到目前为止堆栈顶级运算符已经接收了多少个参数。我的解决方案是使用运算符及其参数的列表并检查其长度。 current_op列表在概念上位于stack的顶部。您可以使用更传统的堆栈,其中包含单个项目,但您需要能够检查堆栈顶部项目的类型(希望不会弹出并重新推送它)。

def prefix_eval(prefix_expr):
    token_list = prefix_expr.split()
    stack = Stack()
    current_op = []

    for token in token_list:
        if token.isdigit():
            current_op.append(int(token))
            while len(current_op) == 3:
                result = doMath(*current_op)
                current_op = stack.pop()
                current_op.append(result)
        else:
            stack.push(current_op)
            current_op = [token]
    return current_op[0]