后缀表达式(逆波兰)设计计算器

package five_stack.suffix;

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

/**
 * Author:jinpma
 * Date :2019/12/4
 */
public class SuffixDemo {
    public static void main(String[] args) {
        //String expression = "111*(32+3)-112";//中缀表达式
        String expression = "10*(13-3)+5*(2-1)";
        SuffixDemo suffixDemo = new SuffixDemo();//中缀表达式转化集合形式
        List<String> list = suffixDemo.changeToList(expression);//中缀表达式集合形式转为后缀表达式
        List<String> suffixList = suffixDemo.changeToSuffix(list);//对后缀表达式,进行计算
        int result = suffixDemo.calculate(suffixList);
        System.out.println(result);
    }
    //3.定义方法,计算后缀表达式(字符串)的结果
    public int calculate(List<String> suffixList){
        //如果是数字,则压栈
        Stack<String> stack = new Stack<>();
        for (String item : suffixList) {
            if (item.matches("\\d+")) {
                stack.push(item);
            }else {//是运算符
                //1.弹出两个数字,进行运算
                //2.将运算结果再压栈
                int num1 = Integer.parseInt(stack.pop());
                int num2 = Integer.parseInt(stack.pop());
                int res = 0;
                switch (item){
                    case "+":
                        res = num1 + num2;
                        break;
                    case "-":
                        res = num2 - num1;//减法:后出栈的-先出栈的
                        break;
                    case "*":
                        res = num1 * num2;
                        break;
                    case "/":
                        res = num2 / num1;//除法:后出栈的-先出栈的
                        break;
                    default:
                        break;
                }
                //将运算结果压栈
                stack.push(""+res);//res为int类型,Stack
            }
        }
        return Integer.parseInt(stack.pop());//栈中最后一个元素即为最终结果
    }
    
    
    //2.定义方法,将中缀表达式集合形式转换为后缀表达式
    public List<String> changeToSuffix(List<String> list){
        //1.定义栈和集合
        Stack<String> s1 = new Stack<>();
        List<String> s2 = new ArrayList<>();
        //2.遍历中缀集合!!!集合元素全部为字符串
        for (String item : list) {
            //2.1如果是数字(字符串),则直接加入s2
            if (item.matches("\\d+")) {//注意:整数的正则表达式为\\d+
                s2.add(item);
            //2.2如果是左括号,直接压栈s1    
            } else if (item.equals("(")) {
                s1.push(item);
            //2.3如果是右括号,则将s1的运算符弹出,并加入s2,直到遇到(左括号为止,并将这一对括号删除    
            } else if (item.equals(")")) {
                while (! s1.peek().equals("(")) {//注意:判断条件只是看一下栈顶元素有没有到(左括号,并不需要弹出,只需要peek()一下
                    s2.add(s1.pop());
                }
                s1.pop();//将左括号弹栈,一对()被消除
            //2.4若为运算符    
            //若item的优先级<=栈中运算符,则将栈中运算符弹出,并且加入s2,这里也不是弹出后比较优先级,而是peek()
            } else{//定义方法property用于判断运算符优先级
                while (s1.size() != 0 && property(item) <= property(s1.peek())){//!!!注意!!!循环弹出栈,需要判断栈是否为空
                    s2.add(s1.pop());
                }
                s1.push(item);//将item压栈
            }
        }
        //3.for循环执行结束,将s1中元素,全部弹出到s2中
        while (s1.size() != 0) {
            s2.add(s1.pop());
        }
        return s2;
    }
    //2.1定义运算符优先级
    public int property(String item){
        int res = 0;
        switch(item){
            case "+":
                res = 1;
                break;
            case "-":
                res = 1;
                break;
            case "*":
                res = 2;
                break;
            case "/":
                res = 2;
                break;
        }
        return res;
    }
    
    
    //1.定义方法,将中缀表达式转换为集合形式
    public List<String> changeToList(String str){
        List<String> list = new ArrayList<>();
        char ch ;//装载每个遍历出来的元素
        String con;//用于多位数数字的拼接(防止111加入集合中变成[1,1,1])
        //遍历字符串
        for (int i = 0; i < str.length(); i++) {
            if ((ch = str.charAt(i)) >57 || (ch) < 48) {//非数字,运算符或者()
                list.add(""+ch);
            }else {//数字,注意多位数的拼接
                con = "";//这一次的多位数拼接,需要将上一次的数字(字符串)先清除
                //满足拼接的判断条件(不是最后一个元素且是数字)
                while ( i < str.length() && (ch = str.charAt(i)) >= 48 && (ch) <= 57 ) {//拼接多位数
                    con += ch;
                    i++;
                }
                list.add(con);
                //!!!特别重要的事,当i+1之后去while中判断,当不满足条件时,i+1(非数字)就被自动跳过了(不会执行if了)
                i--;//while中i++,for中i++,导致数字后的非数字字符被跳过了
            }
        }
        return list;
    }
}

你可能感兴趣的:(数据结构和算法)