中缀表达式转后缀表达式画图详解和代码实现

雨燕双飞 提交于 2020-02-11 18:34:32

中缀表达式转后缀表达式思路步骤分析
1 初始化两个栈:运算符栈s1和存储中间结果的栈s2
2 从左至右扫描中缀表达式
3 遇到运算符时,比较其与s1栈顶运算符的优先级

  • 3.1 如果s1为空,或栈顶运算符为左括号’(’,则直接将此运算符入栈;
  • 3.2 否则,如果优先级比栈顶运算符的高,也直接将此运算符入栈;
  • 3.3 否则,将s1栈顶的运算符弹出并压入s2中。然后又从3.1步开始进行比较(此时带入栈的操作符还是之前那个,只是栈顶元素已变更)

4 遇到操作数时,将其压入s2
5 遇到括号时

  • 5.1 如果是左括号’(’,则直接压入s1
  • 5.2 如果是右括号’)’,则依次弹出s1栈顶的运算符,并压入s2中,直到遇到左括号’('为止,将这个左括号从s1中弹出丢弃(这时候消除了一对括号)

6 重复2~5步,直到中缀表达式扫描完成
7 将s1中剩余的运算符依次弹出并压入s2中
8 依次弹出s2中的元素并输出,并将输出结果逆序,即得到后缀表达式

以中缀表达式1+((2+3)x4)-5举例
(1)当扫描完1+((2+3后,s1和s2栈元素如下
在这里插入图片描述
(2)扫描到一个右括号’)’:
在这里插入图片描述
(3)扫描到一个乘号和数字4:
在这里插入图片描述
(4)扫描到一个右括号’)’:
在这里插入图片描述
(5)扫描到一个减号和5:
在这里插入图片描述
(6)将s1中剩余的运算符依次弹出并压入s2中
在这里插入图片描述
(7)依次弹出s2中的元素并输出,并将输出结果逆序,即得到后缀表达式
s2出栈:- 5 + x 4 + 3 2 1
逆序:1 2 3 + 4 x + 5 -

实现

public class SuffixExpressionDemo {

    public static void main(String[] args) {
        String infixExpression = "1*((23-33)*4)/3";

        List<String> suffixExpression = infix2suffixExpression(infixExpression);
        System.out.println("后缀表达式:"+suffixExpression);

        System.out.println(1*((23-33)*4)/3);
        System.out.println(calculator(suffixExpression));
    }

    //中缀表达式转后缀表达式
    public static List<String> infix2suffixExpression(String infixExpression) {
        List<String> list = string2List(infixExpression); //字符串转成集合
        Stack<String> s1 = new Stack<>(); //存放操作符
        Stack<String> s2 = new Stack<>(); //存放中间结果和数字
        List<String> s2Items = new ArrayList<>(); //存放s2弹出后的元素集
        String result; //结果集
        int i = 0;
        int length = list.size();
        String s; //当前扫描的元素
        String temp;

        while(i < length) {
            s = list.get(i);

            if(s.matches("\\d+")) { //是数字
                s2.add(s);
                i++;
            }else{ //是操作符
                if(s1.isEmpty() || "(".equals(s)) { //栈顶元素为空或当前元素是左括号
                    s1.add(s);
                    i++;
                }else if(")".equals(s)){ //当前元素是右括号
                    temp = s1.peek();
                    while(! temp.equals("(")) {
                        s2.add(s1.pop());
                        temp = s1.peek();
                    }
                    s1.pop();
                    i++;
                }else{
                    String topItem = s1.peek();
                    //栈顶是左括号 或者 当前操作符的优先级比栈顶操作符的高
                    if(topItem.equals("(") || priority(s.charAt(0)) > priority(topItem.charAt(0))) {
                        s1.add(s);
                        i++;
                    }else{
                        //将s1栈顶元素弹出并压入s2
                        s2.add(s1.pop());
                        //注意,这里不能进行i++
                    }
                }
            }
        }

        //将s1剩下的元素压入s2中
        while(! s1.isEmpty()) {
            s2.add(s1.pop());
        }
        
        //s2栈元素依次弹出
        while(! s2.isEmpty()) {
            s2Items.add(s2.pop());
        }

        Collections.reverse(s2Items);
        return s2Items;
    }

    //计算符号的优先级
    public static int priority(char oper) {
        if(oper == '*' || oper == '/') {
            return 1;
        }else if(oper == '-' || oper == '+') {
            return 0;
        }else{
            return -1;
        }
    }

    //将中缀表达式字符串转成集合
    public static List<String> string2List(String infixExpression) {
        List<String> list = new ArrayList<>(); //结果集
        int length = infixExpression.length();
        char c; //当前字符
        int j;
        int i = 0;
        while(i < length){
            c = infixExpression.charAt(i);
            if(c >= 48 && c <= 57) { //数字
                j = i + 1;
                while(j < length && infixExpression.charAt(j) >=48 && infixExpression.charAt(j) <= 57) {
                    j++;
                }
                list.add(infixExpression.substring(i,j));
                i = j;
            }else{ //操作符
                list.add("" + c);
                i++;
            }
        }

        return  list;
    }

    //模拟一个简单的计算器
    public static String calculator(List<String> suffixExpression) {
        Stack<String> stack = new Stack<>();

        for (String s : suffixExpression) {
            if(s.matches("\\d+")) {
                stack.add(s);
            }else{
                if(stack.size() < 2) {
                    throw new RuntimeException("后缀表达式错误");
                }
                int n1 = Integer.parseInt(stack.pop());
                int n2 = Integer.parseInt(stack.pop());
                switch(s) {
                    case "*":
                        stack.add(String.valueOf(n2 * n1));
                        break;
                    case "/":
                        stack.add(String.valueOf(n2 / n1));
                        break;
                    case "+":
                        stack.add(String.valueOf(n2 + n1));
                        break;
                    case "-":
                        stack.add(String.valueOf(n2 - n1));
                        break;
                    default:
                        throw new RuntimeException("后缀表达式错误");
                }
            }
        }
        return stack.pop();
    }
}

结果:
在这里插入图片描述

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!