March.11.2022——中缀表达式转化为后缀表达式统一思路

March.11.2022

中缀表达式转化为后缀表达式统一思路 (8步)
  1. 初始化两个栈:运算符栈s1和储存中间结果的栈s2;

  2. 从左至右扫描中缀表达式;

  3. 遇到操作数时,将其压s2;

  4. 遇到运算符时,比较其与s1栈顶运算符的优先级:

    1). 如果s1为空,或栈顶运算符为左括号“(”,则直接将此运算符入栈;

    2). 否则,若优先级比栈顶运算符的高,也将运算符压入s1;

    3). 否则,将s1栈顶的运算符弹出并压入到s2中,再次转到(4-1)与s1中新的栈顶运算符相比较;

  5. 遇到括号时:

    1. . 如果是左括号“(”,则直接压入s1
    2. . 如果是右括号“)”,则依次弹出s1栈顶的运算符,并压入s2,直到遇到左括号为止,此时将这一对括号丢弃
  6. 重复步骤2至5,直到表达式的最右边

  7. 将s1中剩余的运算符依次弹出并压入s2

  8. 依次弹出s2中的元素并输出,结果的逆序即为中缀表达式对应的后缀表达式

package Zhan;

import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;

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

//如果要使用List 包 那必须要导包!! dlt + enter

public class ZhongZhuiTOHouZhui {

    public static void main(String[] args) {
        //完成将中缀表达式 转化为后缀表达式
        //说明
        //1.   1+((2+3)*4)-5  转换成   1 2 3 + 4 * + 5 -
        //2. 因为直接对字符串 进行操作 不方便,所以需要将 “1+((2+3)*4)-5 ”,中缀表达式存到对应的list中
        // 即“1+((2+3)*4)-5 ” => Arraylist[1,+,(,(,2,+3,),),*,4,-,5]
        //3.将得到的中缀表达式对应的list 转化为后缀表达式
        //即 得到了[1, +, (, (, 2, +, 3, ), *, 4, ), -, 5] 需要转换为  1 2 3 + 4 * + 5 -
        //没有小括号
        //具体的步骤 有8步

        String Expression = "1+((2+3)*4)-5";
        List<String> infixExpressionlist = toInfixExpressionlist(Expression);
        System.out.println(infixExpressionlist);

        //逆波兰表达式 (3+4)*5-6; 其中该式子的逆波兰表达式可以写为 3 4 + 5 * 6 -;
        String sufficExpression = "3 4 + 5 * 6 -";
        //思路
        //1.先将 该计算表达式的逆波兰表达式字符串 放到 Arratlist中
        //2.将 Arraylist 传给一个方法,遍历 Arraylist 配合栈完成计算
        List<String> list = getlistString(sufficExpression);
        System.out.println("list" + list);
        int res = calculate(list);
        System.out.println("计算的结果是" + res);


    }

    //将中缀表达式转化成对应的List
    public static List<String> toInfixExpressionlist(String s) {
        //定义一个List 存放中缀表达式  对应的内容
        List<String> ls = new ArrayList<String>();
        int i = 0; //作为扫描的指针
        String str = "";// 对多位数的拼接
        char c;//每遍历到一个字符 ,就直接放到c
        do {
            //如果 c 是一个非数字的字符 就直接将遍历得到的c加到字符串中
            if ((c = s.charAt(i)) < 48 || (c = s.charAt(i)) > 57) {
                ls.add("" + c);
                i++;
            } else {//如果 c 是一个数  不为个位数的话就将字符串拼接起来
                //这里非常容易出问题!!必须将字符串清空!!!!!!!!!
                str = "";
                //数字在ASC码表中的值 即为48-57 之间
                while (i < s.length() && (c = s.charAt(i)) >= 48 && (c = s.charAt(i)) <= 57) {
                    str += c;
                    i++;
                }
                ls.add(str);
            }

        } while (i < s.length());
        //扫描完毕 返回ls
        return ls;
    }

    //将中缀表达式转换为后缀表达式
    public static List<String> parseSufExpresionList(List<String> ls) {
        //创建一个栈 用于存放运算符
        Stack<String> stack1 = new Stack<String>();
        //创建一个栈 用于存放数字
        //但是考虑到 在中转后缀表达式的时候,数字的栈从来没有使用过出栈操作,并且最后还需要逆序输出
        //这里直接使用List<String> s2;
        //Stack<String> stack2 = new Stack<>();
        List<String> s2 = new ArrayList<String>();

        //遍历ls
        for (String item : ls)
            //如果遍历得到的是一个数 则入栈到s2
            if (item.matches("\\d+")) {
                s2.add(item);
                //请注意 这里是 .equals 不是 .matchs!!!!!
            } else if (item.equals("(")) {
                stack1.push(item);
            } else if (item.equals(")")) {
                while (!stack1.peek().equals("(")) {
                    s2.add(stack1.pop());
                }
                stack1.pop();///将stack1 弹出栈 消除小括号
            } else {
                //当item的运算符的优先级小于等于s1栈顶的运算符,将s1栈顶的运算符弹出并加入s2中,再次转到4.1步骤,与i新的运算符的栈顶比较
                //问题:缺少一个比较运算符优先级的方法
                while (stack1.size() != 0 && Operation.getValue(stack1.peek()) >= Operation.getValue(item)) {
                    s2.add(stack1.pop());
                }
                //还需要将item入栈
                stack1.push(item);
            }
        //将s1剩余的运算符依次弹出并加入s2
                while(stack1.size()!=0){
                   s2.add(stack1.pop());
                }
                return s2;
            }


    private static List<String> getlistString(String sufficExpression) {
            //将后缀表达式按照空格来拆分,拆分成字符串数组
            String[] split = sufficExpression.split(" ");

            //创建一个字符串形式的数组列表 用于接收 被拆分的字符串数组
            ArrayList<String> list = new ArrayList<>();
            for(String ele:split){
                list.add(ele);
            }
            return list;
        }

        //完成对逆波兰表达式的计算
        // 1.从左往右扫描, 将 3 和 4 压入栈中;
        //2.遇到 + 号运算符 弹出 4 和 3 (其中 4为栈顶元素,3为次栈顶元素),计算出 3+4 的值,得到7 将结果7入栈
        //3.将5 入栈
        //4.遇到 * 运算符 ,弹出5 和 7  计算出 5*7=35 将35入栈
        //5.遇到6 将6入栈
        //6.遇到 - 运算符,计算出来 35-6的值 得到最终结果
        //扫描的过程其实就是对list 的遍历
        public static int  calculate(List<String> ls){
            //创建一个栈
            Stack<String> stack = new Stack<>();
            //遍历 ls
            for(String item:ls){
                if(item.matches("\\d+")){// 正则表达式如果遍历到的是一个或者多位数 则 入栈
                    stack.push(item);
                }else { //遍历到的是一个运算符 则pop出两个数字 第一个出栈的是num2 第二个出栈的数命名为num1
                    int num2 = Integer.parseInt(stack.pop());
                    int num1 = Integer.parseInt(stack.pop());
                    //由于出栈的元素的类型为 string  需要转化为int  类型所以调用Integer.parseInt方法 将字符串类型转化为 int 类型方便计算
                    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;
        }

    }





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值