【问题标题】:Java RPN (Reverse Polish Notation) infix to postfixJava RPN(反向波兰表示法)中缀到后缀
【发布时间】:2009-08-24 07:16:47
【问题描述】:

我很确定,堆栈用于构建 PRN,'(' 被忽略,但似乎并非如此。例如:

  • 输入1: 52+(1+2)*4-3
  • 输入2: 52+((1+2)*4)-3
  • 输入 3: (52+1+2)*4-3

输入1和输入2输出应该相同,输入1和输入3应该不同。

  • 输出 1: 52 1 2 + 4 3 - * +
  • 输出 2: 52 1 2 + 4 * 3 - +
  • 输出 3: 52 1 2 + 4 3 - * +

    public static String Infix2(String input) {
        char[] in = input.toCharArray();
        Stack<Character> stack = new Stack<Character>();
        StringBuilder out = new StringBuilder();

        for (int i = 0; i < in.length; i++)
            switch (in[i]) {
            case '+':
            case '*':
            case '-':
                out.append(' ');
                stack.push(in[i]);
                break;
            case ' ':
            case '(':
                break;
            case ')':
                out.append(' ');
                out.append(stack.pop());
                break;
            default:
                out.append(in[i]);
                break;
            }

        while (!stack.isEmpty()) {
            out.append(' ');
            out.append(stack.pop());
        }

        return out.toString();
    }

假设我希望输入 1 和 3 也可以工作,我应该使用什么方法?

编辑: 更改后,“+”、“-”、“*”和“/”适用于给定的输入。


public static String Infix2(String input) {
    if (input == null)
        return "";
    char[] in = input.toCharArray();
    Stack<Character> stack = new Stack<Character>();
    StringBuilder out = new StringBuilder();

    for (int i = 0; i < in.length; i++)
        switch (in[i]) {
        case '+':
        case '-':
            while (!stack.empty()
                    && (stack.peek() == '*' || stack.peek() == '/'))
                out.append(' ').append(stack.pop());
        case '*':
        case '/':
            out.append(' ');
        case '(':
            stack.push(in[i]);
        case ' ':
            break;
        case ')':
            while (!stack.empty() && stack.peek() != '(')
                out.append(' ').append(stack.pop());
            if (!stack.empty())
                stack.pop();
            break;
        default:
            out.append(in[i]);
            break;
        }

    while (!stack.isEmpty())
        out.append(' ').append(stack.pop());

    return out.toString();
}

【问题讨论】:

  • 我不认为你的输出 1 和 2 是正确的:* 在 - 之前,所以应该是 52 1 2 + 4 * 3 - +,不是吗?
  • 您还可以查看此链接以获取 java 中缀转 rpn 转换器:andreinc.net/2010/10/05/…。是python和Java算法调车场算法的简化版。
  • Infix to Postfix using stacks 的副本,以及许多其他人

标签: java algorithm


【解决方案1】:

算法非常简单(和here is a good explanation)。每个操作都有一个绑定权重,+ 和 - 是最低的。有两条规则:

  • 立即打印数字
  • 切勿将较轻的物品放在较重的物品上
  • 左括号入栈
  • 右括号从堆栈中弹出,直到您碰到左括号,然后删除左括号

给定你的第一个例子,52+(1+2)*4-3,这里是堆栈:

 52+          => +
 52+(         => + (
 52+(1+       => + ( + 
 52+(1+2)     => +       //right parentheses popped +
 52+(1+2)*4   => + * 
 52+(1+2)*4-3 => + -     //can't put - on top of *, so pop off *
 ... and then pop the stack until it's empty.

将您的开关循环替换为以下(与您所拥有的最接近的模拟)将为您的三个示例提供正确的答案。在真正的解析器中,您会给每个运算符一个权重并概括弹出机制。

for (int i = 0; i < in.length; i++)
        switch (in[i]) {
        case '+':
        case '-':
            while (!stack.empty() && (stack.peek() == '*' || stack.peek() == '/')) {
                out.append(' ');
                out.append(stack.pop());
            }
            out.append(' ');
            stack.push(in[i]);
            break;
        case '*':
        case '/':
            out.append(' ');
            stack.push(in[i]);
            break;
        case '(':
            stack.push(in[i]);
            break;
        case ')':
            while (!stack.empty() && stack.peek() != '(') {
                out.append(' ');
                out.append(stack.pop());
            }
            stack.pop();
            break;
        default:
            out.append(in[i]);
            break;
        }

【讨论】:

    【解决方案2】:

    不是对特定问题的确切答案,但我建议开发此类算法:查看测试驱动开发 (TDD)。简而言之:为 infix2 方法编写几个单元测试(例如使用 JUnit),您可以在其中为方法提供测试模式(表达式)并测试 infix2 是否产生正确的输出。

    从简单的开始,比如

    assertequals("1", "1"); // positive number
    assertequals("-1", "-1"); // negative number
    assertequals("1+1", "1 1 +"); // simple addition
    assertequals(" 1 + 1 ", "1 1 +"); // simple addition with whitechars
    assertequals(" 1 + +1 ", "1 -1 +"); // simple addition with pos. number & whitechars
    assertequals(" 1 + -1 ", "1 -1 +"); // simple addition with neg. number & whitechars
    assertequals("(1+1)", "1 1 +"); // simple addition with brackets
    

    不要忘记像

    这样的非法表达
    String[] illegalExpressions = {null, "", " ", "1 +", "1 + 1)"};
    

    你的例子的测试用例应该是

    assertequals("52+(1+2)*4-3", "52 1 2 + 4 * 3 -");
    assertequals("52+((1+2)*4)-3", "52 1 2 + 4 * 3 -");
    assertequals("(52+1+2)*4-3", "52 1 + 2 + 4 * 3 -");
    

    【讨论】:

    • 可能在上面的断言中缺少 +,除非它们注定要失败。要通过,应该是assertequals("52+(1+2)*4-3", "52 1 2 + 4 * 3 - +");assertequals("52+((1+2)*4)-3", "52 1 2 + 4 * 3 - +");
    猜你喜欢
    • 2016-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-15
    • 2019-11-23
    相关资源
    最近更新 更多