中缀表达式转换为后缀表达式

中缀表达式转换为后缀表达式

后缀表达式适合计算式进行运算,但是人却不太容易写出来,尤其是表达式很长的情况下,因此在开发中,我们需要将 中缀表达式转成后缀表达式。

1.转换具体步骤:

  • 初始化两个栈:运算符栈s1和储存中间结果的栈s2
  • 从左至右扫描中缀表达式
  • 遇到操作数时,将其压s2
  • 遇到运算符时,比较其与s1栈顶运算符的优先级:
    1. 如果s1为空,或栈顶运算符为左括号“(”,则直接将此运算符入栈
    2. 否则,若优先级比栈顶运算符的高,也将运算符压入s1
    3. 否则,将s1栈顶的运算符弹出并压入到s2中,再次转到(4.1)与s1中新的栈顶运算符相比较。
  • 遇到括号时:
    1. 如果是左括号“(”,则直接压入s1
    2. 如果是右括号“)”,则依次弹出s1栈顶的运算符,并压入s2,直到遇到左括号为止,此时将这一对括号丢弃
  • 重复步骤2至5,直到表达式的最右边
  • 将s1中剩余的运算符依次弹出并压入s2
  • 依次弹出s2中的元素并输出,结果的逆序即为中缀表达式对应的后缀表达式
    - 因为栈的先进后出的方式,因此结果的逆序才是后缀表达式
    - 我们也可以直接用ArrayList来当作存储中间结果的s2,此时list的顺序输出即后缀表达式。

2.代码演示:

以1+((2+3)*4)-5为例演示。

  1. 当我们有一个中缀表达式的时候,需要先将其放在一个列表中,为了方便后续对其操作,使其转换为后缀表达式。同时,操作列表比操作str类型的数据要方便。
public static List<String> toInfixExpressionList(String s){
        //1.定义一个list存放中缀表达式
        ArrayList<String> list = new ArrayList<>();
        int i = 0;
        String ch;//对多位数的拼接
        char c;//每遍历到一个数字/操作符就暂时存储在c中
        do {
            if ((c = s.charAt(i)) < 48 || (c = s.charAt(i)) > 57){//如果是操作符
                list.add("" + c);
                i++;
            }else {//如果是数字,需要考虑多位数的拼接
                ch = "";
                while (i < s.length() && ((c = s.charAt(i)) >= 48 && (c = s.charAt(i) )<= 57)){
                    ch += c;
                    i++;
                }

                list.add(ch);
            }


        }while (i<s.length());

            return list;
    }
  1. 当我们得到中缀表达式的列表后,为了转换成为后缀表达式,因为考虑到不仅有加减乘除的操作符,还有()等改变优先级的方式,具体的转换步骤可参考上文的转换具体步骤。
  2. 由于涉及到操作符的入栈和出栈,涉及到了运算符的优先级问题,因此,我们需要写一个方法来定义运算符的优先级。此处是直接构造了一个类,在类的内部声明了静态方法,同时可以通过类来调用该方法。
优先级的方法
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 getPriority(String oper){
        int res = 0;
        switch (oper){
            case "+":
                res = ADD;
                break;
            case "-":
                res = SUB;
                break;
            case "*":
                res = MUL;
                break;
            case "/":
                res = DIV;
                break;
            default:
                System.out.println("输入错误~");
                break;
        }
        return res;
    }
}
中缀表达式转换为后缀表达式的方法
public static List<String> parseSuffixExpression(List<String> ls){
        //1.定义一个栈,一个ArrayList
        //因为lsit只是用来储存数据,不涉及到栈的pop功能,而且,如果使用栈的话,Pop完后缀表达式后,还需要逆序输出才是真正的后缀表达式
        //没有List方便
        Stack<String> s1 = new Stack<>();//操作符栈
        ArrayList<String> s2 = new ArrayList<>();//存储数据与操作符

        //遍历ls
        for(String s:ls){
            //如果指针指向的是一个数字,则直接加入s2
            if (s.matches("\\d+")){
                s2.add(s);
            }else if("(".equals(s)){
                s1.push(s);
            }else if(")".equals(s)){//当遇到)括号时候,为了和(消掉,需要先将之前的那些操作符全部出栈放到s2中
                while (!s1.peek().equals("(")){
                    s2.add(s1.pop());
                }s1.pop();
            }else {
                //当传入的操作符优先级大于当前栈顶的操作符时候,直接入栈,否则就需要将高优先级的放到s2,直到栈顶的低于当前的优先级
                //构造一个比较优先级高低的方法
                while (s1.size() != 0 && (Operation.getPriority(s1.peek()) > Operation.getPriority(s))){
                    s2.add(s1.pop());
                }s1.push(s);
            }
        }

        //将s1中的剩下来的操作符依次放入s2中
        while (s1.size() != 0){
            s2.add(s1.pop());
        }

        return s2;
    }
  1. 在主函数测试部分,需要先调用中缀表达式转换列表,再调用中缀表达式转换成后缀表达式的方法,然后可以根据之前写的计算的方法来得出数值,验证方法正确与否。
public class PolandNotation {
    public static void main(String[] args) {
        String suffixExpression = "1+((2+3)*4)-5";
        List<String> stringList = toInfixExpressionList(suffixExpression);
        System.out.println("中缀表达式转换成list后: " + stringList);
        List<String> pSEList = parseSuffixExpression(stringList);
        System.out.println("中缀转换为后缀后: " + pSEList);

        int caculate = caculate(pSEList);
        System.out.println("计算结果为: " + caculate);


    }

结果展示

以1+((2+3)*4)-5为例演示,正确结果应该为16.
在这里插入图片描述
出现的两个”输入错误~“的语句是因为在写操作符优先级的时候没有考虑(),因此在调用时候直接进入了default,调用了其中的语句。

递归、排序、查找算法冲冲冲~~~

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值