java 中缀表达式转后缀表达式并计算结果

实现代码如下,已有详细注释,后续再补概念。


package infix_to_suffix;

import com.sun.istack.internal.NotNull;
import com.sun.tools.javac.util.StringUtils;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Stack;

/**
 * @description: 中缀表达式转后缀表达式
 * @author: shicaid
 * @create: 2019-07-24 21:32
 **/
public class InfixToSuffix {

    /**
     * 分隔号---用户美观输出后缀表达式
     */
    private static final String DIVIDE_SYMBOL = " ";

    public static void main(String[] args) {

//        String infix = "9+(3-1)*3+10/2";
//        String infix = "9+(3-1*2)*2+10/2";
//        String infix = "9+(3-1*2+3)*3+10/2";
//        String infix = "1 + (( 2 + 3)* 4 ) - 5";
//        String infix = "(9+(3-1*2+1))*3+10/2";
        String infix = "9+3/1*2/1*2";

        // 避免中缀表达式中的空格影响
        infix = infix.trim();
        infix = infix.replaceAll(" ","");

        // 中缀转后缀结果
        String suffix = InfixToSuffix.transformSuffix(infix);
        System.out.println(suffix);
        // 计算后缀表达式结果
        System.out.println("caculate:");
        System.out.println(infix+"="+ caculate(suffix));

    }


    /**
     * 中缀表达式转换后缀表达式
     *
     * @param infixExpression
     * @return
     */
    public static String transformSuffix(@NotNull String infixExpression) {
        StringBuffer result = new StringBuffer();
        // 将数字和符号分隔出来,数组存储
        String[] infixStrs = splitInfixExpression(infixExpression);
        // 辅助栈
        Stack<String> stack = new Stack<>();

        // begin

        // 1、遍历中缀表达式的数组
        for (String infixStr : infixStrs) {
            // 2、遍历中,如果遇到数字,直接输出
            if(isNumber(infixStr)){
                // 加个空格美观一点
                result.append(infixStr).append(DIVIDE_SYMBOL);
                continue;
            }
            // 3、若不是数字,先判断是否是 ( , 是的话直接入栈
            if(infixStr.equals("(")) {
                stack.push(infixStr);
            } else if(infixStr.equals(")")){
                // 4、如果是 ),则将从栈顶向栈低遍历输出,遇到第一个 (,停止输出,( )这两个皆不输出
                String top = stack.pop();
                while (!top.equals("(")){
                    result.append(top).append(DIVIDE_SYMBOL);
                    top = stack.pop();
                }
            }else {
                // 5、普通的+-*/符号,如果infixStr的优先级小于或等于栈顶的符号,则输出栈顶,
                // 直到infixStr的优先级大于栈顶符号 或 遇到 ( ,infixStr入栈
                if(stack.isEmpty()){
                    // 当然,可能为空栈
                    stack.push(infixStr);
                } else{
                    // 不是空栈
                    String top = stack.peek();
                    while (!top.equals("(") && compareSymbolPriority(infixStr,top) <= 0){
                        // infixStr的优先级小于或等于栈顶的符号
                        result.append(top).append(DIVIDE_SYMBOL);
                        // top出栈
                        stack.pop();
                        // 检查栈
                        if(stack.isEmpty()){
                            top = null;
                            break;
                        }else {
                            // 获取下一个top的值
                            top = stack.peek();
                        }
                    }
                    // infixStr入栈
                    stack.push(infixStr);
                }
            }
        }

        // 6、将栈中剩余的全部出栈
        while (!stack.isEmpty()){
            String top = stack.pop();
            result.append(top).append(DIVIDE_SYMBOL);
        }

        // end

        return result.toString();
    }



    /**
     * 拆分中缀表达式,将整个字符串转为数字符号分离的字符串数组
     *
     * 使得表达式不局限于 个位数 的 加减乘除
     *
     * @param infixExpression 9+(3-1)*3+10/2
     * @return [9,+,(,3,-,1,),*,3,+,10,/,2]
     */
    private static String[] splitInfixExpression(String infixExpression){
        List<String> list = new ArrayList<>();
        StringBuffer numer = new StringBuffer();
        for (char c : infixExpression.toLowerCase().toCharArray()) {
            if(isNumber(c+"")){
                numer.append(c);
                continue;
            }
            // 当不是数字时,输出上一个数字
            String numberStr = numer.toString();
            if(!numberStr.isEmpty()){
                list.add(numberStr);
            }
            numer.delete(0,numer.length());
            // 符号的话直接输出
            list.add(c+"");
        }
        String numberStr = numer.toString();
        if(!numberStr.isEmpty()){
            list.add(numberStr);
        }
        return list.toArray(new String[]{});
    }


    /**
     *
     * @Description: 比较两个符号的优先级: / = *  > - = +
     * @Param:
     * @return: >0 first > last;
     *          =0 first = last;
     *          <0 first < last;
     * @Author: shicaid
     * @Date: 2019-07-24
     */
    private static int compareSymbolPriority(String first, String last) {

        int firstNum = virturalSymbolNumber(first);
        int lastNum = virturalSymbolNumber(last);

        if(firstNum * lastNum == 0)
            throw new IllegalArgumentException("argument("+first+","+last+") is illegal !");

        return firstNum - lastNum;
    }

    /**
     * 检查字符是否是数字
     *
     * @param s
     * @return
     */
    private static boolean isNumber(String s) {
        if(s.length() > 1){
            // 在此处,符号只有1位,所以大于1位的都是数字(int但不限于int,float自然仍不支持啦)
            return true;
        }
        char c = s.charAt(0);
        return c >= 48 && c <= 57;
    }

    /**
     * 将符号转为虚拟数字
     *
     * @param c
     * @return
     */
    private static int virturalSymbolNumber(String c){
        int result;

        switch (c){
            case "/":
                result = 2;
                break;
            case "*":
                result = 2;
                break;
            case "-":
                result = 1;
                break;
            case "+":
                result = 1;
                break;
            default:
                result = 0;
                break;
        }
        return result;
    }

    /**
     * 计算后缀表达式的值
     * @param suffixExpression
     * @return
     */
    public static int caculate(String suffixExpression){
        Stack<String> numberStack = new Stack<>();

        for (String s : suffixExpression.trim().split(DIVIDE_SYMBOL)) {
            if(isNumber(s)){
                numberStack.push(s);
                continue;
            }  // 不是数字,是符号,计算啦
            String top = numberStack.pop();
            String second = numberStack.pop();
            int topInt = Integer.valueOf(top);
            int secondInt = Integer.valueOf(second);

            int tempResult = 0;

            switch (s){
                case "/":
                    tempResult = secondInt / topInt;
                    break;
                case "*":
                    tempResult = secondInt * topInt;
                    break;
                case "-":
                    tempResult = secondInt - topInt;
                    break;
                case "+":
                    tempResult = secondInt + topInt;
                    break;
                default:
                    break;
            }
            // 最终结果入栈
            numberStack.push(tempResult+"");

        }
        return Integer.valueOf(numberStack.pop());

    }


}


你可能感兴趣的:(Java,数据结构)