使用Stacks Java的Infix到Postfix

时间:2014-11-02 12:05:02

标签: java algorithm data-structures stack

我正在尝试编写一个程序来将中缀表达式转换为后缀表达式。

我使用的算法如下:

1. Create a stack
2. For each character t in the expression
   - If t is an operand, append it to the output
   - Else if t is ')',then pop from the stack till '(' is encountered and append 
     it to the output. do not append '(' to the output.
   - If t is an operator or '('
        -- If t has higher precedence than the top of the stack, then push t 
           on to the stack.
        -- If t has lower precedence than top of the stack, then keep popping 
           from the stack and appending to the output until either stack is 
           empty or a lower priority operator is encountered.

    After the input is over, keep popping and appending to the output until the
    stack is empty.

这是我的代码,打印出错误的结果。

public class InfixToPostfix
{
    private static boolean isOperator(char c)
    {
        return c == '+' || c == '-' || c == '*' || c == '/' || c == '^'
                || c == '(' || c == ')';
    }

    private static boolean isLowerPrecedence(char op1, char op2)
    {
        switch (op1)
        {
            case '+':
            case '-':
                return !(op2 == '+' || op2 == '-');

            case '*':
            case '/':
                return op2 == '^' || op2 == '(';

            case '^':
                return op2 == '(';

            case '(':
                return true;

            default:
                return false;
        }
    }

    public static String convertToPostfix(String infix)
    {
        Stack<Character> stack = new Stack<Character>();
        StringBuffer postfix = new StringBuffer(infix.length());
        char c;

        for (int i = 0; i < infix.length(); i++)
        {
            c = infix.charAt(i);

            if (!isOperator(c))
            {
                postfix.append(c);
            }

            else
            {
                if (c == ')')
                {

                    while (!stack.isEmpty() && stack.peek() != '(')
                    {
                        postfix.append(stack.pop());
                    }
                    if (!stack.isEmpty())
                    {
                        stack.pop();
                    }
                }

                else
                {
                    if (!stack.isEmpty() && !isLowerPrecedence(c, stack.peek()))
                    {
                        stack.push(c);
                    }
                    else
                    {
                        while (!stack.isEmpty() && isLowerPrecedence(c, stack.peek()))
                        {
                            Character pop = stack.pop();
                            if (pop != '(')
                            {
                                postfix.append(pop);
                            }
                        }
                    }

                    stack.push(c);
                }
            }
        }

        return postfix.toString();
    }

    public static void main(String[] args)
    {
        System.out.println(convertToPostfix("A*B-(C+D)+E"));
    }
}

该程序应打印AB*CD+-E+,但它正在打印AB*-CD+E。 为什么输出不正确?

此外,是否有更优雅的解决方案来解决这个问题。如果您有或知道,请分享。

5 个答案:

答案 0 :(得分:5)

问题在于你的其他部分:

               if (!stack.isEmpty() && !isLowerPrecedence(c, stack.peek()))
                {
                    stack.push(c);
                }
                else
                {
                    while (!stack.isEmpty() && isLowerPrecedence(c, stack.peek()))
                    {
                        Character pop = stack.pop();
                        if (pop != '(')
                        {
                            postfix.append(pop);
                        }
                    }
                }

                stack.push(c);

所以在这里你看到堆栈不为空且优先级匹配更高时,使用stack.push()两次推送相同的c元素。

所以把这个stack.push放在else部分或者从if条件中删除push。

另一个问题是,当最后你在堆栈中有一些操作符时,你不会弹出它们。

以下是我为您的案例提出的代码:

private static boolean isOperator(char c)
{
    return c == '+' || c == '-' || c == '*' || c == '/' || c == '^'
            || c == '(' || c == ')';
}

private static boolean isLowerPrecedence(char op1, char op2)
{
    switch (op1)
    {
        case '+':
        case '-':
            return !(op2 == '+' || op2 == '-');

        case '*':
        case '/':
            return op2 == '^' || op2 == '(';

        case '^':
            return op2 == '(';

        case '(':
            return true;

        default:
            return false;
    }
}

public static String convertToPostfix(String infix)
{
    Stack<Character> stack = new Stack<Character>();
    StringBuffer postfix = new StringBuffer(infix.length());
    char c;

    for (int i = 0; i < infix.length(); i++)
    {
        c = infix.charAt(i);

        if (!isOperator(c))
        {
            postfix.append(c);
        }

        else
        {
            if (c == ')')
            {

                while (!stack.isEmpty() && stack.peek() != '(')
                {
                    postfix.append(stack.pop());
                }
                if (!stack.isEmpty())
                {
                    stack.pop();
                }
            }

            else
            {
                if (!stack.isEmpty() && !isLowerPrecedence(c, stack.peek()))
                {
                    stack.push(c);
                }
                else
                {
                    while (!stack.isEmpty() && isLowerPrecedence(c, stack.peek()))
                    {
                        Character pop = stack.pop();
                        if (c != '(')
                        {
                            postfix.append(pop);
                        } else {
                          c = pop;
                        }
                    }
                    stack.push(c);
                }

            }
        }
    }
    while (!stack.isEmpty()) {
      postfix.append(stack.pop());
    }
    return postfix.toString();
}

public static void main(String[] args)
{
    System.out.println(convertToPostfix("A*B-(C+D)+E"));
}

答案 1 :(得分:1)

我认为以上答案不正确。

这是我更正的版本:

package Stack;

import java.util.Stack;

/*
 * 
Algorithm
1. Scan the infix expression from left to right.
2. If the scanned character is an operand, output it.
3. Else,
…..3.1 If the precedence of the scanned operator is greater than the precedence of the operator in the stack(or the stack is empty), push it.
…..3.2 Else, Pop the operator from the stack until the precedence of the scanned operator is less-equal to the precedence of the operator residing on the top of the stack. Push the scanned operator to the stack.
4. If the scanned character is an ‘(‘, push it to the stack.
5. If the scanned character is an ‘)’, pop and output from the stack until an ‘(‘ is encountered.
6. Repeat steps 2-6 until infix expression is scanned.
7. Pop and output from the stack until it is not empty.

 */
public class InfixToPostFixEvalution {

    private static boolean isOperator(char c) {
        return c == '+' || c == '-' || c == '*' || c == '/' || c == '^' || c == '(' || c == ')';
    }

    private static int getPrecedence(char ch) {
        switch (ch) {
        case '+':
        case '-':
            return 1;

        case '*':
        case '/':
            return 2;

        case '^':
            return 3;
        }
        return -1;
    }

    // A utility function to check if the given character is operand
    private static boolean isOperand(char ch) {
        return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z');
    }

    public static String convertToPostfix(String infix) {
        Stack<Character> stack = new Stack<Character>();
        StringBuffer postfix = new StringBuffer(infix.length());
        char c;

        for (int i = 0; i < infix.length(); i++) {
            c = infix.charAt(i);

            if (isOperand(c)) {
                postfix.append(c);
            } else if (c == '(') {
                stack.push(c);
            }
            // If the scanned character is an ‘)’, pop and output from the stack
            // until an ‘(‘ is encountered.
            else if (c == ')') {

                while (!stack.isEmpty() && stack.peek() != '(') {
                    postfix.append(stack.pop());
                }
                if (!stack.isEmpty() && stack.peek() != '(')
                    return null;
                else if(!stack.isEmpty())
                    stack.pop();
            }
            else if (isOperator(c)) // operator encountered
            {
                if (!stack.isEmpty() && getPrecedence(c) <= getPrecedence(stack.peek())) {
                    postfix.append(stack.pop());
                }
                stack.push(c);
            }
        }

        while (!stack.isEmpty()) {
            postfix.append(stack.pop());
        }
        return postfix.toString();
    }

    public static void main(String[] args) {
        System.out.println(convertToPostfix("a+b*(c^d-e)^(f+g*h)-i"));
    }
}

答案 2 :(得分:0)

此代码插入&#34;(&#34;以及堆栈并相应地删除。只是另一种实现中缀到后缀的方法。这里检查是直到我在堆栈中找不到优先级较低的运算符我会弹出超出值。例如,如果堆栈有 - 并且下一个运算符是+,它将弹出 - 因为它具有相同的优先级。

我已经添加了自定义堆栈实现,但是java提供的普通堆栈也可以在原地使用

import chapter4.LinkedListStack(custom stack implementation);

public class InfixToPostfix {

public String infixToPostfix(String str) {
    LinkedListStack<String> stack = new LinkedListStack<>();
    String[] st = str.split("");
    String result = "";
    for (String s : st) {
        if (operator(s)) {
            if (")".equals(s)) {
                while (!stack.isEmpty() && !"(".equals(stack.getTop())) {
                    result += stack.pop();
                }
                if (!stack.isEmpty()) {
                    stack.pop();
                }
            } else {
                if (!stack.isEmpty() && !isLowerPrecedence(s, stack.getTop())) {
                    stack.push(s);
                } else {
                    while (!stack.isEmpty() && isLowerPrecedence(s, stack.getTop())) {
                        String top = stack.pop();
                        if (!"(".equals(top)) {
                            result += top;
                        }
                    }
                    stack.push(s);
                }
            }
        } else {
            result += s;
        }
    }
    while (!stack.isEmpty()) {
        result += stack.pop();
    }

    return result;
}

private boolean isLowerPrecedence(String s, String s1) {
    switch (s) {
    case "+":
        return !("+".equals(s1) || "(".equals(s1));
    case "-":
        return !("-".equals(s1) || "(".equals(s1));

    case "*":
        return "/".equals(s1) || "^".equals(s1) || "(".equals(s1);
    case "/":
        return "*".equals(s1) || "^".equals(s1) || "(".equals(s1);

    case "^":
        return "(".equals(s1);

    case "(":
        return false;

    default:
        return false;
    }

}

private boolean operator(String s) {
    return "+".equals(s) || "-".equals(s) || "*".equals(s) || "/".equals(s) || "^".equals(s) || "(".equals(s) ||
            ")".equals(s);
}

public static void main(String[] args) {
    InfixToPostfix itp = new InfixToPostfix();
    System.out.println("The Postfix expression for A*B-(C+D)+E is: " + itp.infixToPostfix("A*B-(C+D)+E"));
    System.out.println("The Postfix expression for 1+2*4/5-7+3/6 is: " + itp.infixToPostfix("1+2*4/5-7+3/6"));
    System.out.println("The Postfix expression for a+(b*c)/d is: " + itp.infixToPostfix("a+(b*c)/d"));
}
}
public class LinkedListStack<E> {

private Node<E> head;

private static class Node<E> {
    E item;
    Node<E> next;

    public Node(E item, Node<E> next) {
        this.item = item;
        this.next = next;
    }
}

public void push(E item) {
    System.out.println("push: " + item);
    Node<E> newNode = new Node<>(item, null);
    newNode.next = head;
    head = newNode;
}

public E pop() {
    if (isEmpty()) {
        System.out.println("stack is Empty -> empty stack exception");
        return null;
    }
    System.out.println("pop: " + head.item);
    E data = head.item;
    head = head.next;
    return data;
}

public boolean isEmpty() {
    return head == null;
}

public E getTop() {
    return head.item;
}
}

答案 3 :(得分:0)

我认为问题出在这里

private static boolean isLowerPrecedence(char op1, char op2)
{
switch (op1)
{
    .....
    case '(':
        return true;
    .....
}

对于'(',应返回false。

答案 4 :(得分:0)

此解决方案需要在原始表达式周围加上大括号,但与我看过的其他答案相比,它非常简单直接。仅适用于可能需要的人,因为该帖子是旧帖子。

public static String InfixToPostfix(String origin) 
{

   String[] params = origin.split(" ");

   Stack<String> ops = new Stack<>();

   Stack<String> vals = new Stack<>();

 for (int i = 0; i < params.length; i++)
    {

switch (params[i]) {
    case "(":
        ;
        break;
    case "+":
        ops.push(params[i]);
        break;
    case "-":
        ops.push(params[i]);
        break;
    case "*":
        ops.push(params[i]);
        break;
    case "/":
        ops.push(params[i]);
        break;
    case "sqrt":
        ops.push(params[i]);
        break;
// Token not operator or paren: push double value.
       case ")":
            String d1 = vals.pop();
            String d2 = vals.pop();
            String op = ops.pop();
         vals.push("( " + d2 + " " + d1 + " "+ op + " )");
         break;
    default:
            vals.push(params[i]);
               break;    
        }
    }
   // System.out.print(vals.pop());
    return vals.pop();

      }