逆波兰计算器——Java实现

实现逆波兰计算器,主要通过以下三个步骤:
1. 将输入的字符串(表达式)按每个数值、操作符单独存储在字符串数组infix中。例如infix中的字符串可以是“-2.3333”、“1.2138”、“+”、“*”、“(”等等。
2. 通过栈和操作符的优先级的比较,将中缀表达式infix转换为后缀表达式postfix。
3. 通过栈,计算posfix的结果。

下面是具体实现的代码:

import java.util.*;

public class  ReversePolishNotation{
    private String ex; //输入表达式(未分割)
    private String[] infix = new String[100];//存储中缀表达式
    private String[] postfix = new String[100];//存储后缀表达式

    public ReversePolishNotation(){}

    /* 将表达式按数值和操作符进行分割 */
    private void exSplit() {  
        int len = 0;
        for(int i = 0  ; i < ex.length() ; i++) {
            char c = ex.charAt(i);
            int startIndex = i;
            //负数
            if( c == '-' && ( i == 0 || ex.charAt(i-1) < '0' || ex.charAt(i-1) > '9') ) {
                do {
                    i++;
                    if(i == ex.length()){//已经超出了字符串末尾
                        break;
                    }
                    c = ex.charAt(i);
                }while( (c >= '0' && c <= '9') || c == '.') ; //判断是否为非个位数或者小数
                infix[len] = ex.substring(startIndex , i);//[startIndex,i)
                len++;
                i--;//continue无法忽略最后的i++
                continue;
            }
            //正数
            if(c >= '0' && c <= '9'){
                do {
                    i++;
                    if(i == ex.length()){
                        break;
                    }
                    c = ex.charAt(i);
                }while( (c >= '0' && c <= '9') || c == '.') ; 
                infix[len] = ex.substring(startIndex , i);
                len++;
                i--;
                continue;  
            }
            infix[len] = ex.substring(startIndex ,startIndex + 1);
            len++;
        }

    }
    /* 将中缀表达式变为后缀表达式 */
    private void infixToPostfix(){
        this.exSplit();
        ArrayDeque<String> stack = new ArrayDeque<>();

        int i = 0;
        for(String str:infix){
            //最后将留在栈里的操作符依次出栈
            if(str == null){
                while(stack.peekFirst() != null) {
                    postfix[i++] = stack.pop();
                } 
                break;
            }
            //注意:Java中字符串是引用类型,两个引用类型变量,只有他们指向同一个对象时,==判断才会返回true;String已经重写了Object的equals()方法,只要两个字符串所包含的字符序列相同,返回true。
            if( !str.equals("(") && !str.equals(")") && !str.equals("+") && !str.equals("-")&& !str.equals("*") && !str.equals("/")){
                postfix[i++] = str;
            }
            else {
                String topStr = stack.peekFirst();

                if(topStr == null){
                    stack.push(str);
                    continue;
                }

                switch(str){
                    //"("默认入栈,当待入栈的操作符为")"时,小括号之间的操作符依次出栈
                    case ")": {
                        while(!stack.peekFirst().equals("(")){  
                            postfix[i++] = stack.pop();
                        }
                        stack.pop();//弹出'('
                        break;
                    }

                    //栈顶操作符优先级大于等于待入栈的操作符,栈顶的操作符需要先执行,因此出栈
                    //计算顺序为从左到右,所以优先级相等的时候,先入栈的先计算
                    case "*": {
                        //到栈顶的操作符优先级小于待入栈的操作符位置
                        while(topStr.equals("*") || topStr.equals("/") ){

                            postfix[i++] = stack.pop();
                            topStr = stack.peekFirst();
                            if(topStr == null){
                                break;    
                            }
                        }
                        break;
                    }
                    case "/": {
                        while(topStr.equals("*") || topStr.equals("/") ){

                            postfix[i++] = stack.pop();
                            topStr = stack.peekFirst();
                            if(topStr == null){
                                break;    
                            }
                        }
                        break;
                    }
                    case "+": {
                        while(topStr.equals("*") || topStr.equals("/") || topStr.equals("+") || topStr.equals("-") ){   
                            postfix[i++] = stack.pop();
                            topStr = stack.peekFirst();
                            if(topStr == null){
                                break;    
                            }
                        }
                        break;
                    }
                    case "-": {
                        while(topStr.equals("*") || topStr.equals("/") || topStr.equals("+") || topStr.equals("-")){
                            postfix[i++] = stack.pop();
                            topStr = stack.peekFirst();
                        if(topStr == null){
                                break;    
                            }
                        }
                        break;
                    }
                }
                //")"不用入栈,用于匹配"("
                if(!str.equals(")")){
                    stack.push(str);
                }
            }   
        }
    }
    /* 后缀表达式*/
    public double calculate(String ex){
        this.ex = ex;
        this.infixToPostfix();
        ArrayDeque<Double> stack = new ArrayDeque<>();
        double popFirst,popSecond;

        for(String str: postfix){
            if(str == null){
                break;
            }

            if( !str.equals("(") && !str.equals(")") && !str.equals("+") && !str.equals("-")&& !str.equals("*") && !str.equals("/")){
                stack.push( Double.parseDouble(str) );
            }
            else{
                switch(str){
                    case "*": {
                        popFirst = stack.pop();
                        popSecond = stack.pop(); 
                        stack.push(popSecond * popFirst);
                        break;
                    }
                    case "/": {
                        popFirst = stack.pop();
                        popSecond = stack.pop(); 
                        stack.push(popSecond / popFirst);
                        break;
                    }
                    case "+": {
                        popFirst = stack.pop();
                        popSecond = stack.pop(); 
                        stack.push(popSecond + popFirst);
                        break;
                    }
                    case "-": { 
                        popFirst = stack.pop();
                        popSecond = stack.pop(); 
                        stack.push(popSecond - popFirst);
                        break;
                    }
                }
            }
        }
        return stack.pop();
    }
    /* 输出后缀表达式 */
    private void outPostfix(){
        for(String str:postfix){
            if(str == null){
                break;
            }
            System.out.print(str + " ");
        }
        System.out.println();
    }
    //测试
    public static void main(String[] args) {

        ReversePolishNotation rpn = new ReversePolishNotation();
        System.out.println("计算结果:" + rpn.calculate("-1.23+2*(3.14+0+4.1*1*(-2*5+20)+3+3)*4--2.34"));
        System.out.println("后缀表达式:");
        rpn.outPostfix();
    }
}

猜你喜欢

转载自blog.csdn.net/XindaBlack/article/details/82594596
今日推荐