【问题标题】:Turn Postfix Python Code to Prefix将 Postfix Python 代码转为前缀
【发布时间】:2016-05-27 00:33:18
【问题描述】:

我正在从 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 + /'))

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

【问题讨论】:

  • 旁注:doMath 可以通过创建dict 映射到operator 模块提供的各种函数来简化为dict 查找。

标签: python stack postfix-notation prefix-operator


【解决方案1】:

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

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

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]

【讨论】:

    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 2021-10-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-05
      • 2020-04-04
      • 1970-01-01
      • 2013-11-08
      • 2013-04-02
      相关资源
      最近更新 更多