中缀表达式转后缀表达式

10 篇文章 0 订阅

之前一篇文章讲了逆波兰式计算器的实现,我们一般使用的是前缀表达式,但是对于计算机来说,后缀表达式是一种更好的选择。下面讲下中缀表达式转换为后缀表达式。

分析

中缀表达式之前说过,就比如1+((2+3)*4)-5这样的计算表达式,但是如何转换成后缀表达式呢?

1,定义两个栈s1和s2,运算符栈和用于存储中间结果的栈s2

2,从左往右扫描中缀表达式

3,遇到操作数,将其压入s2。

4,遇到(,直接将它压入s2

5,遇到),则一直弹出s1里面的有运算符,直到遇到(为止,并将弹出的结果压入s2,之后将一对括号丢弃

6,遇到有运算符时,先与栈顶的符号优先级做一个比较,优先级小于等于栈顶的字符,将栈顶的运算符弹出,反复比较,直到比栈顶的优先级大,就直接将该字符压入s1.

7,重复以上步骤,将s1剩余的操作符依次弹出并加到s2中。

8,s2中弹出,然后在做反序,就是后缀表达式的结果

代码实现

说明:本例中的用于保存结果的栈s2用list集合代替,因为用栈的话,最后的结果还需要做反序,十分不方便

package cn.mrlij.stack;

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

/**
 * 中缀表达式转后缀表达式
 */
public class PolandNotation {
    public static void main(String[] args) {
        String exp = "1+((2+3)*4)-5";
        List<String> toinfix = toinfixList(exp);
       System.out.println(toinfix);
        List<String> list = tosuffList(toinfix);
        System.out.println(list);
    }


    /**
     * 遍历表达式,并将遍历的结果放入list中
     * @param exp 表达式
     * @return
     */
    public static List<String> getStrList(String exp){
        String arr[] = exp.split(" ");//将字符串遍历得到数组
        List<String> list = new ArrayList<>();
        for(String str : arr){
            list.add(str);
        }
        return list;
    }
    //将前缀表达式转换为相应的list,便于操作
    public static  List<String> toinfixList(String str){
        List<String> list = new ArrayList<>();
        String s = "";//用于字符串拼接
        char c = ' ';//用于保存字符
        int index = 0;//定义索引
        //
        do{
            //非数字,添加到list中  0的ASCII为48,9的ASCII为57
            if(str.charAt(index)<48 || str.charAt(index)>57 ){
                list.add(""+str.charAt(index));
                index++;
            }else {
                //为数字
                while (index<str.length()&&(str.charAt(index)>=48 && str.charAt(index)<=57)){
                    s = "";//将s清空
                    //往后找数字,是否存在多位数字
                    s += str.charAt(index);
                    index++;
                }
                list.add(s);
            }
        }while (index<str.length());
        return list;
    }
    //前缀表达式转换成后缀表达式的方法
    public static  List<String> tosuffList(List<String> list){
        Stack<String> s1 = new Stack<>();//定义一个用于存放前缀表达式字符的栈
        List<String> s2 = new ArrayList<>();//用于存放后缀表达式字符的集合
        //遍历list
        for(String item : list){
            if(item.matches("\\d+")){
                s2.add(item);
            }else if(item.equals("(")){
                s1.push(item);
            }else if(item.equals(")")){
                //遇到),依次弹出s1中的操作符号,直到遇到(为止,此时将一对括号丢弃
                while(!s1.peek().equals("(")){
                    s2.add(s1.pop());
                }
                s1.pop();
            }else {
                while (s1.size()!=0&&(Oper.getValue(s1.peek())>=Oper.getValue(item))){
                    s2.add(s1.pop());
                }
                s1.push(item);
            }
        }
        while (s1.size()!=0){
            s2.add(s1.pop());
        }
        return s2;
    }

    //计算表达式
    public static int calc(List<String> list ){
        //创建存放字符串的栈
        Stack<String> stack = new Stack<>();
        //遍历list
        for (int i = 0;i<list.size();i++){
            //正则表达式匹配是否是数字
            if(list.get(i).matches("\\d+")){
                stack.push(list.get(i));//是数字则放入栈中
            }else {
                int num2 = Integer.parseInt(stack.pop());//弹出数字1
                int num1 = Integer.parseInt(stack.pop());//弹出数字2
                int res = 0;
                //进行运算
                if(list.get(i).equals("+")){
                    res = num1 + num2;
                }else if(list.get(i).equals("-")){
                    res = num1 - num2;
                }else if(list.get(i).equals("*")){
                    res = num1 * num2;
                }else if(list.get(i).equals("/")){
                    res = num1/num2;
                }else {
                    throw new RuntimeException("不是操作符号!");
                }
                stack.push(""+res);
            }
        }
        //留在栈中的值就是最后的计算表达式结果
        return Integer.parseInt(stack.pop());
    }
}
class Oper{
    public static int ADD = 1;
    public static int SUB = 1;
    public static int MUL = 2;
    public static int DIV = 2;

    public static int getValue(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;
    }
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值