中缀表达式变为后缀表达式

/**
 * @ClassName SymbolicPriority
 * @Description 符号优先级设置
 * @Author lzq
 * @Date 2018/12/3 12:04
 * @Version 1.0
 **/
public class SymbolicPriority {
    public static final int LEFT_BRACKET = 4;  //左括号
    public static final int RIGHT_BRACKET = 1;  //右括号
    public static final int ADD = 2;       //加号
    public static final int MINUS = 2;    //减号
    public static final int TIMES = 3;    //乘号
    public static final int DIVIDE = 3;   //除号
    public static final int ERROR = -1;   //不是任何计算符号
}
import java.util.Arrays;

/**
 * @ClassName Stack
 * @Description 通用栈
 * @Author lzq
 * @Date 2018/11/13 15:32
 * @Version 1.0
 **/
public class Stack {
    int top;
    T[] elem;

    public Stack() {
        this(10);
    }

    public Stack(int number) {
        this.elem = (T[])new Object[number];
        this.top = 0;
    }

    /**
     * 判空
     * @return
     */
    public boolean isEmpty() {
        return this.top == 0;
    }

    /**
     * 判满
     * @return
     */
    public boolean isFull() {
        return this.top == this.elem.length;
    }

    /**
     * 入栈
     * @param val
     */
    public void push(T val) {
        if(isFull()) {
            this.elem = Arrays.copyOf(elem,elem.length*2);
        }
        this.elem[top++] = val;
    }

    /**
     * 出栈
     */
    public void pop() {
        if(isEmpty()) {
            return;
        }
        this.top--;
    }

    /**
     * 获得栈顶元素
     * @return
     */
    public T get_top() {
        if(isEmpty()) {
            return null;
        }
        return this.elem[top-1];
    }
}
/**
 * @ClassName Suffix
 * @Description 后缀表达式的四种运算及中缀转后缀
 * @Author lzq
 * @Date 2018/12/3 12:00
 * @Version 1.0
 **/
public class Suffix {
    /**
     * 获取符号的优先级
     * @param x
     * @return
     */
    public int get_priority(char x) {
        int priority = 0;
        switch (x) {
            case '+':
                priority = SymbolicPriority.ADD;
                break;
            case '-':
                priority = SymbolicPriority.MINUS;
                break;
            case '*':
                priority = SymbolicPriority.TIMES;
                break;
            case '/':
                priority = SymbolicPriority.DIVIDE;
                break;
            case '(':
                priority = SymbolicPriority.LEFT_BRACKET;
                break;
            case ')':
                priority = SymbolicPriority.RIGHT_BRACKET;
                break;
                default:
                    priority = SymbolicPriority.ERROR;
                    System.out.println("符号错误!");
        }
        return priority;
    }

    /**
     * 中缀转后缀
     * @return
     */
    public StringBuilder infix_to_suffix(String string) {
        char[] chars = string.toCharArray();
        StringBuilder stringBuilder = new StringBuilder();
        int i = 0;
        Stack stack = new Stack<>();
        while (i < chars.length) {
            //判断当前字符是不是数字
            if (Character.isDigit(chars[i])) {
                stringBuilder.append(chars[i]);  //如果是数字,直接输出
            } else if(get_priority(chars[i]) == -1){  //输入的表达式有非数字和非计算符号
                return null;
            } else {
                /**
                 * 如果栈是空的,或者入栈的优先级比栈顶元素优先级高,或者栈顶元素是一个左括号
                 * 直接入栈
                 */
                if (stack.isEmpty() || (chars[i] != ')' && stack.get_top() == '(')||
                        get_priority(chars[i]) > get_priority(stack.get_top()) ) {
                    stack.push(chars[i]);
                } else {
                    //如果当前字符是右括号,那么一直出栈,出到左括号出栈为止
                    if (chars[i] == ')') {
                        while (!stack.isEmpty() && stack.get_top() != '(') {
                            stringBuilder.append(stack.get_top());
                            stack.pop();
                        }
                        if(stack.isEmpty()) {
                            System.out.println("右括号多了!");
                            return null;
                        }else {
                            //循环出来是栈顶肯定是左括号,不要它了
                            stack.pop();
                        }
                    } else {
                        //否则的话,当前字符就是计算符号,出栈到优先级比他高的为止
                        while (!stack.isEmpty() && get_priority(chars[i]) <= get_priority(stack.get_top())) {
                            if (stack.get_top() == '(') {  //碰到左括号就不能出了
                                break;
                            }
                            stringBuilder.append(stack.get_top());
                            stack.pop();
                        }
                        //出完了自己再入栈
                        stack.push(chars[i]);
                    }
                }
            }
            i++;
        }
        //把栈里面的元素全拿出来
        while(!stack.isEmpty()) {
            if(stack.get_top() == '(') {
                System.out.println("左括号多了!");
                return null;
            }
                stringBuilder.append(stack.get_top());
                stack.pop();
        }
        return stringBuilder;
    }

    /**
     * 后缀表达式的计算
     * @param string
     * @return
     */
    public int suffix(String string) {
        if(infix_to_suffix(string) == null) {
            System.out.println("输入不正确!");
            return Integer.MIN_VALUE;
        }
        String s1 = new String(infix_to_suffix(string)); //首先要拿到后缀表达式
        Stack stack = new Stack<>();
        int i = 0,temp1,temp2,temp = 0;
        while (i < s1.length()) {
            if(Character.isDigit(s1.charAt(i))) {
                stack.push(Integer.parseInt(String.valueOf(s1.charAt(i))));
            }else {
                //后缀表达式不可能把计算符号放前面,就不需要判空了
                //注意这个有先后顺序的,栈顶的元素作为减数、除数...
                temp1 = stack.get_top();
                stack.pop();
                //出栈一次后,栈顶的元素作为被减数、被除数...
                temp2 = stack.get_top();
                stack.pop();
                temp = operation(s1.charAt(i),temp2,temp1);
                stack.push(temp);
            }
            i++;
        }
        return temp;
    }

    /**
     * 计算
     * @param m
     * @param x
     * @param y
     * @return
     */
    public int operation(char m,int x,int y) {
        int temp = 0;
        switch (m) {
            case '+':
                temp = x+y;
                break;
            case '-':
                temp = x-y;
                break;
            case '*':
                temp = x*y;
                break;
            case '/':
                temp = x/y;
                break;
                default:
                    System.out.println("符号错误!");
                    break;
        }
        return temp;
    }
}

测试代码:

public static void main(String[] args) {
        for(;;) {
            Scanner scan = new Scanner(System.in);
            System.out.println("请输入中缀表达式:");
            String string = scan.nextLine();
            Suffix s = new Suffix();
            System.out.println(string + "的后缀表达式为:" + s.infix_to_suffix(string));
            System.out.println("后缀表达式计算结果为:" + s.suffix(string)+"\n");
    }
请输入中缀表达式:
((1+2)*(4-2)-1)*5-(2+2)*(3+3)
((1+2)*(4-2)-1)*5-(2+2)*(3+3)的后缀表达式为:12+42-*1-5*22+33+*-
后缀表达式计算结果为:1

请输入中缀表达式:
2+3*5-4*((5-3)
左括号多了!
2+3*5-4*((5-3)的后缀表达式为:null
左括号多了!
输入不正确!
后缀表达式计算结果为:-2147483648

请输入中缀表达式:
9+(3-1))*3
右括号多了!
9+(3-1))*3的后缀表达式为:null
右括号多了!
输入不正确!
后缀表达式计算结果为:-2147483648

请输入中缀表达式:

实现原理

你可能感兴趣的:(算法)