数据结构——后缀表达式

一、需要自定义的优先级

package com_1.constant;

//运算符自定义的优先级

public class Constant {

    public static final int PRI_ERROR = -1;

    //栈外左括号
    public static final int PRI_LEFT_OUT = 1;

    //栈内乘
    public static final int PRI_MULTY_IN = 2;
    //栈内除
    public static final int PRI_DIV_IN = 2;

    //栈外乘
    public static final int PRI_MULTY_OUT = 3;
    //栈外除
    public static final int PRI_DIV_OUT = 3;

    //栈内加
    public static final int PRI_PLUS_IN = 4;
    //栈内减
    public static final int PRI_SUB_IN = 4;

    //栈外加
    public static final int PRI_PLUS_OUT = 5;
    //栈外减
    public static final int PRI_SUB_OUT = 5;

    //栈内左括号
    public static final int PRI_LEFT_IN = 10;
    //栈外右括号
    public static final int PRI_RIGHT_OUT = 10;
}
    //得到当前运算符的优先级
    public int getPri(char oper,boolean inStack){
        int pri = Constant.PRI_ERROR;
        //在栈内
        if(inStack){
            switch (oper){
                case '+':
                    pri = Constant.PRI_PLUS_IN;
                    break;
                case '-':
                    pri = Constant.PRI_SUB_IN;
                    break;
                case '*':
                    pri = Constant.PRI_MULTY_IN;
                    break;
                case '/':
                    pri = Constant.PRI_DIV_IN;
                    break;
                case '(':
                    pri = Constant.PRI_LEFT_IN;
                    break;
                    default:
                        pri = Constant.PRI_ERROR;
                        break;
            }
        }
        //栈外
        else{
            switch (oper){
                case '+':
                    pri = Constant.PRI_PLUS_OUT;
                    break;
                case '-':
                    pri = Constant.PRI_SUB_OUT;
                    break;
                case '*':
                    pri = Constant.PRI_MULTY_OUT;
                    break;
                case '/':
                    pri = Constant.PRI_DIV_OUT;
                    break;
                case '(':
                    pri = Constant.PRI_LEFT_OUT;
                    break;
                case ')':
                    pri = Constant.PRI_RIGHT_OUT;
                    break;
                    default:
                        pri = Constant.PRI_ERROR;
                        break;
            }
        }
        return pri;
    }

二、中缀表达式到后缀表达式的转化

*判断数字字符

Character.isDigit(strMid.charAt(i))
    //中缀表达式转为后缀表达式
    public void strMidToLast(String strMid,char[] strLast){

        //栈
        char[] stack = new char[strMid.length()];//栈的大小
        int top = 0;//栈顶指针

        //strMid下标
        int i = 0;
        //strLast下标
        int j = 0;

        //当前栈内运算符的优先级
        int pri_in = Constant.PRI_ERROR;
        //当前栈外运算符的优先级
        int pri_out = Constant.PRI_ERROR;

        //遍历中缀表达式
        while(i != strMid.length()){
            //是数字——存入后缀表达式
            if(Character.isDigit(strMid.charAt(i))){
                strLast[j] = strMid.charAt(i);
                i ++;
                j ++;
            }
            //是运算符——进行栈的操作
            else{
                //栈空——直接进栈
                if(top == 0){
                    stack[top ++] = strMid.charAt(i);
                    i ++;
                }
                //栈不为空——比较优先级
                else{
                    //栈内
                    pri_in = getPri(stack[top - 1],true);
                    //栈外
                    pri_out = getPri(strMid.charAt(i),false);

                    //栈外优先级高——入栈
                    if(pri_out < pri_in){
                        stack[top ++] = strMid.charAt(i);
                        i ++;
                    }
                    //栈内优先级高——出栈,并存入后缀表达式
                    else if(pri_in < pri_out){
                        strLast[j ++] = stack[top - 1];
                        top --;
                    }
                    //优先级相等——括号匹配,出栈不存入,i往后走
                    else{
                        top --;
                        i ++;
                    }
                }

            }
        }
        //遍历结束,跳出循环,如果栈不为空,将运算符依次出栈并存入后缀表达式
        while(top != 0){
            strLast[j ++] = stack[-- top];
        }
    }

三、根据后缀表达式进行计算


    //两个数字运算
    public int getResult(int a,int b,char oper){
        int result = 0;
        switch (oper){
            case '+':
                return a + b;
            case '-':
                return a - b;
            case '*':
                return a * b;
            case '/':
                return a / b;
        }
        return -1;
    }

    /*
    根据后缀表达式计算结果
    遍历后缀表达式
    将数字入栈。碰到运算符,出栈两次,进行运算,并将运算结果再入栈
     */
    public int arithmetic(char[] strLast){

        //栈
        int[] stack = new int[strLast.length];
        int top = 0;
        //后缀表达式下标
        int i = 0;
        //两个操作数
        int num1 = 0;
        int num2 = 0;
        //运算结果
        int result = 0;

        //后缀表达式遍历
        while(i != strLast.length){
            //是数字——入栈
            if(Character.isDigit(strLast[i])){
                //先将当前字符转化为int类型
                String str1 = Character.toString(strLast[i]);
                stack[top ++] = Integer.parseInt(str1);
            }
            //空格或默认值
            else if(strLast[i] == ' ' || strLast[i] == '\u0000'){

            }
            //运算符——出栈两次,进行运算并将结果入栈
            else{
                num1 = stack[-- top];//右操作数
                num2 = stack[-- top];//左操作数
                char oper = strLast[i];
                //进行运算
                result = getResult(num2,num1,oper);
                //结果再次入栈
                stack[top ++] = result;
            }
            i ++;
        }
        return result;
    }

猜你喜欢

转载自blog.csdn.net/weixin_42479293/article/details/84929411
今日推荐