中缀表达式转后缀表达式+后缀表达式的计算+中缀表达式的合法性校验

下面所述方法支持整数的+、-、*、/、()操作

运行结果:

描述:

中缀表达式:通用的算术或逻辑公式表示方法,操作符是以中缀的形式处于操作数的中间,平时常用的算术表示方法。

后缀表达式:  后缀表达式是将操作符置于操作数的后面,如:3 4 +;后缀表达式的表达方式不唯一,如中缀表达式(a+b+c*d)/e,ab+cd*+e/与abcd*++e/都是其后缀表达式。

1.中缀表达式的合法性校验

分析:

将输入的表达式按操作符(+、-、*、/、左右括号)与数字(包括负数)以空格隔开,再将按照空格分隔后的字符串存入数组中,检验表达式合法分为两步,首先操作符不能在首位或者末位,其次操作符不能连续,括号必须匹配(遍历数组+栈检验),通过检验返回中缀表达式,没有通过检验返回null。

代码:

public static String check(String s){
        if(s == null || s.length() == 0){
            return null;
        }
        //1.添加空格
        StringBuffer sb = new StringBuffer();
        for(int i=0,len=s.length(); i<len; i++) {
            char tmp = s.charAt(i);
            if (tmp > '9' || tmp < '0') {//操作符
                if(tmp == '-'&&(i==0 ||(i!=0 && s.charAt(i-1)=='('))){//负数的-号
                    int j=i;
                    i++;
                    while(i<len && '0'<=s.charAt(i) && s.charAt(i)<='9') {
                        i++;
                    }
                    sb.append(s.substring(j,i)).append(" ");
                    i--;
                }else{
                    sb.append(String.valueOf(tmp)).append(" ") ;
                }
            }else{
                int j=i;
                while(i<len && '0'<=s.charAt(i) && s.charAt(i)<='9') {
                    i++;
                }
                sb.append(s.substring(j,i)).append(" ");
                i--;
            }
        }
        String[] str = sb.toString().split(" ");
        //2.检验中缀表达式是否合法
        //2.1操作符"+","-","*","/"不能出现在首位,末位
        if("+".equals(str[0]) || "-".equals(str[0]) ||"*".equals(str[0]) ||"/".equals(str[0]) ||
                "+".equals(str[str.length-1]) || "-".equals(str[str.length-1])
                ||"*".equals(str[str.length-1]) ||"/".equals(str[str.length-1]) ){
            return null;
        }
        //2.2操作符"+","-","*","/"“不能连续,括号成对匹配
        Stack<String> stack = new Stack<>();
        for(int i=0; i<str.length; i++){
            if("(".equals(str[i])){//左括号入栈
                stack.push(str[i]);
            }else if(")".equals(str[i])){//右括号出栈
                if(!("(".equals(stack.pop()))){
                    return null;
                }
            }else if(("+".equals(str[i]) || "-".equals(str[i]) ||"*".equals(str[i]) ||"/".equals(str[i]))
                    && ("+".equals(str[i-1]) || "-".equals(str[i-1]) ||"*".equals(str[i-1]) ||"/".equals(str[i-1]))){//连续操作符
                return null;
            }
        }
        return stack.empty() ? sb.toString() : null;//栈不为空说明括号不匹配
    }

测试:

2.中缀表达式转后缀表达式

分析:

创建两个栈:stack1存操作符,stack2存数字(也存一些计算结果),将传入的中缀表达式以空格分隔存入数组str,遍历数组

情况一:如果是+、-、*、/、( 操作符,放入stack1中,

情况二:如果是数字,放入stack2中,判断stack1的栈顶是否是*或/,是则在stack2中弹出两个数字,在stack1中弹出一个操作符,将数字1+" " +数字2+" " +操作符(这相当于局部的一个结果)存入stack2中,执行上述操作直到stack1的栈顶不为*或/。

情况三:如果是 ),在stack2中弹出两个数字,在stack1中弹出一个操作符,将数字1+" " +数字2+" " +操作符 存入stack2中,执行上述操作直到stack1的栈顶弹出( ,此时相当于计算完了一对括号中的表达式,结果存在stack2的栈顶,这时还要判断stack1的栈顶是否是*或/,是的话就满足情况二,进行情况二的操作。

遍历完毕,stack1中只剩了+、-两种操作符,将stack1和stack2的内容逆置,这样就符合+、-操作的顺序了,于是在两个栈中又进行弹出操作符和数字的操作,直到stack1为空,stack2存的就是最终的后缀表达式。

以-2 * ( 1 - 2 ) + 6 / 3进行演示:

代码:

public static String intoSuffix(String infix){
        Stack<String> stack1 = new Stack<>();//放操作符的栈
        Stack<String> stack2 = new Stack<>();//放数字的栈
        String[] str = infix.split(" ");
        for(int i=0,len = str.length; i<len; i++){
            String tmp = str[i];
            if(")".equals(str[i])) {
                String mark = stack1.pop();//弹出操作符
                while ((!"(".equals(mark)) && (!stack1.empty())) {
                    //弹出两个数字
                    String number2 = stack2.pop();
                    String number1 = stack2.pop();
                    String result = number1 + " " + number2 + " " + mark;//结果
                    stack2.push(result);//结果入栈
                    mark = stack1.pop();//更新操作符
                }
                while(!stack1.empty() && ("*".equals(stack1.peek()) ||"/".equals(stack1.peek()))){
                    //弹出两个数字
                    String number2 = stack2.pop();
                    String number1 = stack2.pop();
                    String mark1 = stack1.pop();
                    String result = number1 + " " + number2 + " " + mark1;//结果
                    stack2.push(result);//结果入栈
                }
            }else if("+".equals(str[i]) || "-".equals(str[i]) ||
                    "*".equals(str[i]) ||"/".equals(str[i])||"(".equals(str[i])){//操作符
                stack1.push(tmp);
            }
            else{//数字
                stack2.push(str[i]);
                while(!stack1.empty() && ("*".equals(stack1.peek()) ||"/".equals(stack1.peek()))){
                    //弹出两个数字
                    String number2 = stack2.pop();
                    String number1 = stack2.pop();
                    String mark1 = stack1.pop();
                    String result = number1 + " " + number2 + " " + mark1;//结果
                    stack2.push(result);//结果入栈
                }
            }
        }
        Stack<String> stack11 = new Stack<>();//放操作符
        Stack<String> stack22 = new Stack<>();//放数字
        while(!stack1.empty()){
            stack11.push(stack1.pop());
        }
        while(!stack2.empty()){
            stack22.push(stack2.pop());
        }
        while(!stack11.empty()){
            String mark = stack11.pop();//弹出操作符
            String number1 = stack22.pop();//弹出两个数字
            String number2 = stack22.pop();
            String result = number1+" "+number2+" "+mark;//结果
            stack22.push(result);//结果入栈
        }
        return stack22.pop();
    }

3.后缀表达式的计算

分析:

以空格分隔后缀表达式,结果存入数组str中,创建栈stack,遍历数组,遇到数字压栈,遇到操作符(+、-、*、/)在栈中弹出两个数字,计算出结果,如操作符是+,就计算数字1+数字2,将计算结果压栈,遍历完毕返回栈顶的结果

以-2 1 2 - * 6 3 / +进行演示:

代码:

public static int calculateSuffix(String suffix){
       String[] s = suffix.split(" ");
       Stack<Integer> stack = new Stack<>();
       for(int i=0; i<s.length; i++){
           if(("+".equals(s[i])) || ("-".equals(s[i])) || ("*".equals(s[i])) || ("/".equals(s[i]))){//操作符
               int number2 = stack.pop();
               int number1 = stack.pop();
               int result = 0;
               if("+".equals(s[i])){
                   result = number1+number2;
               }else if("-".equals(s[i])){
                   result = number1-number2;
               }else if("*".equals(s[i])){
                   result = number1*number2;
               }else if("/".equals(s[i])){
                   result = number1/number2;
               }
               stack.push(result);
           }else{//数字
               stack.push(Integer.parseInt(s[i]));
           }
       }
       return stack.pop();
    }

主函数:

public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String str= sc.nextLine();
        System.out.print("中缀表达式:");
        String infix = check(str);
        if(infix == null){
            System.out.println("表达式不合法");
        }else{
            System.out.println(infix);
            String suffix = intoSuffix(infix);
            System.out.println("后缀表达式:"+suffix);
            System.out.println("计算结果:"+calculateSuffix(suffix));
        }
    }

猜你喜欢

转载自blog.csdn.net/qq_43109561/article/details/89496367