1. 程式人生 > >資料結構——字尾表示式

資料結構——字尾表示式

一、需要自定義的優先順序

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;
    }