欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【数据结构14】中缀表达式转后缀表达式并计算表达式结果

程序员文章站 2024-02-26 19:23:40
...

1.具体步骤

【数据结构14】中缀表达式转后缀表达式并计算表达式结果

2. 思路分析

将中缀表达式转换为后缀表达式:1+((2+3)*4)-5
【数据结构14】中缀表达式转后缀表达式并计算表达式结果

3. 代码分析

public class PolanNotation {
    public static void main(String[] args) {
        //完成一个将中缀表达式转后置表达式的功能
        //1. 1+((2+3)*4)-5 装成 1 2 3 + 4 * + 5 -
        //2. 先将中缀表达式转成表达式对应的list,[1,+,(,(,2,+,3,),*,4,),-,5]
        //3. 将中缀表达式对应的List转成后缀表达式对应的list,[1,2,3,+,4,*.+,5,-]

        String expression = "1+((2+3)*4)-5";
        List<String> prefixExpression = toPrefixExpression(expression);
        System.out.println("中缀表达式对应的list:"+prefixExpression);
        List<String> suffixExpressionList = parseSuffixExpressionList(prefixExpression);
        System.out.println("后缀表达式对应的list:"+suffixExpressionList);
			
		//计算逆波兰表达式的值
        System.out.println(calculate(suffixExpressionList));
    }

    //将中缀表达式转成对应的额list
    public static List<String> toPrefixExpression(String s){
        //定义一个List,存放中缀表达式对应的内容
        List<String> ls = new ArrayList<>();
        int i=0;//指针,用于遍历中缀表达式
        String str;//对多位数的拼接工作
        char c;//每遍历一个字符,就放入到c中
        do{
            //如果c是一个非数字,加入到ls中
            if((c=s.charAt(i))<48 ||(c=s.charAt(i))>57){
                ls.add(""+c);
                i++;//i需要后移
            }else{//如果是一个数,需要考虑多位数
                str="";
                while((i<s.length()) && (c=s.charAt(i))>=48 && (c=s.charAt(i))<=57){
                    str += c;
                    i++;
                }
                ls.add(str);
            }
        }while (i<s.length());
        return  ls;
    }

    //将一个逆波兰表达式,依次将数据和运算符放入到ArrayList中
    public static List<String> getListString(String suffixExpression){
        String[] split = suffixExpression.split(" ");
        List<String> list = new ArrayList<String>();
        for(String ele:split){
            list.add(ele);
        }
        return list;
    }

    //将中缀表达式对应的List转成后缀表达式对应的list,[1,2,3,+,4,*.+,5,-]
    public static List<String> parseSuffixExpressionList(List<String> ls){
        //定义两个栈
        Stack<String> s1 = new Stack<>();//符号栈
        //因为s2在转换过程中,没有pop操作,并且最后还需要逆序输出,因此可以使用List代替栈
        ArrayList<String> s2 = new ArrayList<>();
        //遍历ls
        for(String item :ls){
            //如果是一个数,就入栈
            if(item.matches("\\d+")){
                s2.add(item);
            }else if(item.equals("(")){
                s1.push(item);
            }else if(item.equals(")")){
                //如果是右括号,则依次弹出s1栈顶的运算符,并压入s2,直到遇到左括号为止,此时将这一对括号丢弃
                while (!s1.peek().equals("(")){
                    s2.add(s1.pop());
                }
                s1.pop();//将左括号消除
            }else{
                //当item的优先级小于等于栈顶的优先级,将s1栈顶的运算符弹出并压入到s2中,
                // 再次转到(4-1)与s1中新的栈顶运算符相比较;
                //写一个比较优先级高低的方法
                while (s1.size()!=0 && Operation.getValue(s1.peek())>=Operation.getValue(item)){
                    s2.add(s1.pop());
                }
                s1.push(item);
            }
        }
        //将s1中剩余的运算符依次弹出并压入s2
        while (s1.size()!=0){
            s2.add(s1.pop());
        }
        return s2;//因为存放到list中,所以正常输出就是对应的逆波兰表达式
    }
    
    /*
        从左至右扫描,将3和4压入堆栈;
        遇到+运算符,因此弹出4和3(4为栈顶元素,3为次顶元素),计算出3+4的值,得7,再将7入栈;
        将5入栈;
        接下来是×运算符,因此弹出5和7,计算出7×5=35,将35入栈;
        将6入栈;
        最后是-运算符,计算出35-6的值,即29,由此得出最终结果
     */
    public static int calculate(List<String> ls){
        //创建栈
        Stack<String> stack = new Stack<String>();
        //遍历List
        for(String item:ls){
            //使用正则表达式取出数
            if(item.matches("\\d+")){//匹配多位数
                //入栈
                stack.push(item);
            }else{
                //pop出两个数并运算在入栈
                int num2 = Integer.parseInt(stack.pop());
                int num1 = Integer.parseInt(stack.pop());
                int res = 0;
                if(item.equals("+")){
                    res = num1+num2;
                }else if(item.equals("-")){
                    //后弹出的数减去先弹出的数
                    res = num1-num2;
                }else if(item.equals("*")){
                    res = num1* num2;
                }else if(item.equals("/")){
                    res = num1/num2;
                }else {
                    throw new RuntimeException("运算符有误");
                }
                //将整数转成字符串
                stack.push(""+res);
            }
        }
        //最后的结果就是留在栈中的数据
        return Integer.parseInt(stack.pop());
    }

}
class Operation{
    private static int ADD=1;
    private static int SUB=1;
    private static int MUL=2;
    private static int DIV=2;

    //写一个方法,返回对应的优先级数字
    public static int getValue(String operation){
        int result = 0;
        switch (operation){
            case "+":
                result = ADD;
                break;
            case "-":
                result = SUB;
                break;
            case "*":
                result = MUL;
                break;
            case "/":
                result = DIV;
                break;
            default:
                System.out.println("不存在该运算符");
                break;
        }
        return result;
    }
}

【数据结构14】中缀表达式转后缀表达式并计算表达式结果