中缀表达式转后缀及计算

276 阅读2分钟

1、中缀表达式转后缀

(1)转换过程

  • 初始化两个栈,运算符栈s1和存中间结果的栈s2(由于s2不用进行出栈操作,所以为了方便,我们可以用list来代替)
  • 从左到右扫描中缀表达式:
    • 遇到操作数的时候,直接将其压入s2
    • 遇到运算符的时候,则比较其与s1栈顶元素的优先级: (1)如果s1为空,或栈顶元素为左括号(,则直接将该运算符入栈。
      (2)如果优先级比栈顶元素高,也将此运算符压入栈中。
      (3)否则,将s1栈顶的运算符弹出并压入到s2中,再次转到(1)进行比较
    • 遇到括号的时候 (1)如果是左括号“(”,则直接压入s1。
      (2)如果是右括号,则依次弹出栈顶的运算符,并压入s2,直到遇到左括号为止,最后将这一对括号丢掉。
    • 将s1中剩余的元素依次压入s2中,s2结果的逆序就是中缀对应的后缀表达式

(2)实现代码如下:

public class PolandExpression2 {

    //将表达式转换为list
    public List<String> expressionToList(String expression){
        List<String> expressionList = new ArrayList<>();
        for(int i = 0;i < expression.length();i++){
            char temp = expression.charAt(i);
            if(isOperation(temp)){
                expressionList.add(temp + "");
            }
            else{
                String str = "" + temp;
                i++;
                while(i < expression.length() && !isOperation(expression.charAt(i))){
                    str = str + expression.charAt(i);
                    i++;
                }
                expressionList.add(str);
                i--;
            }
        }
        return expressionList;
    }
    public boolean isOperation(char a){
        return a == '+' || a == '-' || a == '*' || a == '/' || a == '(' || a == ')';
    }

    //中缀表达式转后缀
    public List<String> Convert(List<String> expression){
        Stack<String> stack = new Stack<>();
        List<String> result = new ArrayList<>();
        for (String item : expression){
            if(!isOperation(item.charAt(0))){
                result.add(item);
            }
            else if(item.equals("(") || stack.isEmpty() || priority(item) > priority(stack.peek())){
                stack.push(item);
            }
            else if(item.equals(")")){
                while(!stack.peek().equals("(")){
                    result.add(stack.pop());
                }
                stack.pop();
            }
            else {
                while (!stack.isEmpty() && priority(stack.peek()) >= priority(item)){
                    result.add(stack.pop());
                }
                stack.push(item);
            }
        }
        while(!stack.isEmpty()){
            result.add(stack.pop());
        }
        return result;
    }

    public int priority(String item) {
        if(item.equals("+") || item.equals("-")){
            return 1;
        }
        else if(item.equals("*") || item.equals("/")){
            return 2;
        }
        return 0;
    }

    public static void main(String[] args) {
        String expression = "1+((2+3)*4)-5";
        PolandExpression2 temp = new PolandExpression2();
        List<String> expression1 = temp.expressionToList(expression);
        System.out.println(temp.Convert(expression1).toString());

    }
}

2、利用后缀表达式计算结果

(1)计算步骤

  • 从左至右扫描表达式,如果碰见操作数,则直接入栈。
  • 遇到操作符,则从栈中弹出两个元素,并将计算结果放入栈中。
  • 栈中最后一个元素就是最终的计算结果

(2) 实现代码

class Solution {
    public int evalRPN(String[] tokens) {
        Stack<String> stack = new Stack<>();
        for(int i = 0;i < tokens.length;i++){
            if(!tokens[i].equals("+") && !tokens[i].equals("-") && !tokens[i].equals("*") && !tokens[i].equals("/")){
                stack.push(tokens[i]);
            }
            else {
                int num2 = Integer.parseInt(stack.pop());
                int num1 = Integer.parseInt(stack.pop());
                if(tokens[i].equals("+")){
                   stack.push(String.valueOf(num1 + num2));
                }
                else if(tokens[i].equals("-")){
                    stack.push(String.valueOf(num1 - num2));
                }
                else if(tokens[i].equals("*")){
                    stack.push(String.valueOf(num1 * num2));
                }
                else if(tokens[i].equals("/")){
                    stack.push(String.valueOf(num1 / num2));
                }
            }
        }
        String result = stack.pop();
        return Integer.parseInt(result);
        // return Integer.parseInt(stack.pop());
    }
}

(3)写的更简洁的代码如下

class Solution {
    public int evalRPN(String[] tokens) {
        Deque<Integer> stack = new LinkedList();
        for (int i = 0; i < tokens.length; ++i) {
            if ("+".equals(tokens[i])) {        // leetcode 内置jdk的问题,不能使用==判断字符串是否相等
                stack.push(stack.pop() + stack.pop());      // 注意 - 和/ 需要特殊处理
            } else if ("-".equals(tokens[i])) {
                stack.push(-stack.pop() + stack.pop());
            } else if ("*".equals(tokens[i])) {
                stack.push(stack.pop() * stack.pop());
            } else if ("/".equals(tokens[i])) {
                int temp1 = stack.pop();
                int temp2 = stack.pop();
                stack.push(temp2 / temp1);
            } else {
                stack.push(Integer.valueOf(tokens[i]));
            }
        }
        return stack.pop();
    }
}