后缀表达式与中缀表达式求值

public class Evaluate {




    public static double[] parseNum(char[]str,int i){
        double num=0;
        int k=-1;
        for(;i<str.length;i++){
            if(str[i]>='0'&&str[i]<='9'){
                num=num*10+str[i]-'0';
                if(k!=-1)
                    k++;
            }
            else if(str[i]=='.')
                k++;
            else
                break;
        }
        while (k>0){
            num/=10;
            k--;
        }
        double[] ret=new double[2];
        ret[0]=num;
        ret[1]=i;
        return ret;
    }


   /*
        后缀表达式求值。
        遇到数值就放到栈中,遇到操作符,就从栈顶取出操作数,运算后结果放回栈中。
    */
    public static double postEvaluate(char[] strs){
        LinkedList<Double>numStack=new LinkedList<>();
        for(int i=0;i<strs.length&&strs[i]!='#';i++){
            if(strs[i]>='0'&&strs[i]<='9'){
                double []ret=parseNum(strs,i);
                numStack.push(ret[0]);
                i=(int)ret[1]-1;
            }else if(strs[i]=='*'){
                double n2=numStack.pop();
                double n1=numStack.pop();
                numStack.push(n1*n2);
            }else if(strs[i]=='/'){
                double n2=numStack.pop();
                double n1=numStack.pop();
                numStack.push(n1/n2);
            }else if(strs[i]=='+'){
                double n2=numStack.pop();
                double n1=numStack.pop();
                numStack.push(n1+n2);
            }else if(strs[i]=='-'){
                double n2=numStack.pop();
                double n1=numStack.pop();
                numStack.push(n1-n2);
            }else if(strs[i]=='.')
                continue;
        }
        return numStack.pop();
    }


    public static int priority(char c){

        switch (c){

            case '#':
            case '(':return -1;
            case '+':
            case '-':
                return 1;
            case '*':
            case '/':
                return 2;
            default:
                return -1;
        }

    }

    public static boolean isOp(char c){

        switch (c){
            case '+':
            case '-':
            case '*':
            case '/':
                return true;
            default:
                return false;
        }
    }

    /*
        将中缀表达式的符号插入到操作数的适当位置,就可以用后缀表达式求值了。
        如果遇到左括号,说明一个新的表达式开始,将 左括号入栈
        如果遇到又括号,说明一个表达式结束,将栈中元素一直退栈放到后缀表达式,直到遇到第一个左括号,然后将左括号也退栈
        如果遇到操作符,那么将栈顶优先级大于等于它的操作符全部退栈放到后缀表达式,直到栈顶优先级比它小,那么把该操作符加入

       思想: 后缀表达式与中缀表达式操作数顺序相同,不同的就是操作符顺序, 只要根据优先级安排操作符位置就好。
       遇到数,就直接放进去。
       遇到操作符,因为不确定后面的操作符的优先级是不是比它高,所以先放到栈中保存,同时,如果栈顶那些操作符优先级大于等于它的话,
       可以确定那些操作符可以先进行运算,所以把栈顶比它优先级大和相等的全部退栈,直到遇到比它优先级小的。

     */
    public static double mieEvaluate(char strs[]){
        char[] pstrs=new char[strs.length*2];
        LinkedList<Character>opStack=new LinkedList<>();
        int i=0,j=0;
        for(;i<strs.length;i++){
            if(strs[i]>='0'&&strs[i]<='9'||strs[i]=='.')
                pstrs[j++]=strs[i];
            else if(strs[i]=='(')
                opStack.push('(');
            else if(strs[i]==')'){
                while (opStack.peek()!='(')
                    pstrs[j++]=opStack.pop();
                opStack.pop();
            }else if(isOp(strs[i])){
                pstrs[j++]=' ';
                while (!opStack.isEmpty()&&priority(opStack.peek())>=priority(strs[i]))
                    pstrs[j++]=opStack.pop();
                opStack.push(strs[i]);
            }
        }
        while (!opStack.isEmpty())
            pstrs[j++]=opStack.pop();
        pstrs[j++]='#';
        return postEvaluate(pstrs);

    }


    public static void main(String []args){

        Scanner scanner=new Scanner(System.in);
        while (scanner.hasNext()){
            String line=scanner.nextLine();
            System.out.println(mieEvaluate(line.toCharArray()));
        }
    }


}

猜你喜欢

转载自blog.csdn.net/yzr1183739890/article/details/68951982