栈实现中序表达式转后序表达式,并求出逆波兰表达式的值

package com.yg.stack;/*
@author  GeQiLin
@date    2020/2/22  20:24
*/

import org.hibernate.validator.internal.util.privilegedactions.NewProxyInstance;
import org.springframework.web.bind.annotation.RestController;

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

/*
 * 求解逆波兰表达式
 * */
public class PolandNotation {
    public static void main(String[] args) {
      /*
      //计算后续表达式
      String lastExpersion = "1 2 + 5 * 6 -";
        //将lastExpersion分解成单个字符并存入arraylist数组中
        List list = transferArrayList(lastExpersion);
        //遍历list集合进行对应的计算操作
        int res = 0;
        res = calculator(list);
        System.out.println(lastExpersion + "=" + res);*/

        //中序转后序
        String expersion = "1+((2+3)*4)-5";
        List infixExpersion = new ArrayList<>();
        infixExpersion = toInfixExpersionList(expersion);
        System.out.println("中缀表达式:"+infixExpersion);
        List suffixExpersion = new ArrayList<>();
        suffixExpersion = parseSuffixExpersion(infixExpersion);
        System.out.println("后缀表达式:"+suffixExpersion);
        System.out.println("expersion="+calculator(suffixExpersion));




    }

    /*
    将中序表达式的list转为后序表达式的list
    准备一个栈s1,ArrayList集合s2
    * 1.遍历中序表达式
    2.如果是操作数直接入s2
    3.如果是括号:
    左括号(:直接入s1
    右括号):将s1栈顶元素依次出栈然后放入s2直至栈顶为(为止
    4.如果是操作符
    s1为空则存入s1
    栈顶值为(则如s1
    否则
    优先级如果大于栈顶运算符直接入s1
    优先级如果小于等于栈顶运算符则将s1的栈顶运算符加到s2中然后再次进行4操作
    * */
    private static List parseSuffixExpersion(List list) {
        Stack s1 = new Stack<>();
        List s2 = new ArrayList<>();
        for (String oper : list) {
            if (oper.matches("\\d+")) {
                //如果是操作数;
                s2.add(oper);
            } else if (oper.equals("(")) {
                s1.push(oper);
            } else if (oper.equals(")")) {
                while (!s1.peek().equals("(")) {
                    s2.add(s1.pop());
                }
                s1.pop();//将"( "出栈
            } else {
                //是操作符,当oper的优先级大于栈顶时将oper加入s1,否者将s1栈顶出栈加入s2并循环判断
                while (s1.size() != 0 && getPriority(s1.peek().charAt(0)) >= getPriority(oper.charAt(0))) {
                    s2.add(s1.pop());
                }
                s1.push(oper);
            }

        }
        while (s1.size() != 0) {
            s2.add(s1.pop());
        }

        return s2;
    }

    //进行逆波兰表达式的运算规则
    //从左至右扫描逆波兰表达式
    //1.如果是操作数就进栈
    //2.如果是操作符,就将两个操作数出栈进行运算
    private static int calculator(List list) {
        if (list == null) {
            throw new RuntimeException("集合为空");
        }
        Stack stack = new Stack<>();
        for (String oper : list) {
            //如果oper是操作数则入栈
            if (oper.matches("\\d+")) {
                stack.push(oper);
            } else {
                //oper是字符则将两个书pop出
                int num2 = Integer.parseInt(stack.pop());
                int num1 = Integer.parseInt(stack.pop());
                int res = 0;
                //实际计算操作
                res = doCalculator(num1, num2, oper);
                stack.push("" + res);
            }
        }
        return Integer.parseInt(stack.pop());
    }

    //进行实际的计算处理
    private static int doCalculator(int num1, int num2, String oper) {
        char c = oper.charAt(0);
        int res = 0;
        switch (c) {
            case '+':
                res = num1 + num2;
                break;

            case '-':
                res = num1 - num2;
                break;
            case '*':
                res = num1 * num2;
                break;
            case '/':
                if (num1 == 0) {
                    throw new RuntimeException("被除数不能为0");
                }
                res = num1 / num2;
                break;
            default:
                System.out.println("参数有误");
                break;
        }
        return res;
    }

    //将逆波兰表达式逐个存入list集合中
    private static List transferArrayList(String lastExpersion) {
        if (lastExpersion == "") {
            System.out.println("逆波兰表达式为空!!");
            return null;
        }
        String[] operArr = lastExpersion.split(" ");
        //如果最后一位不是操作符而是操作数则表达式错误
        if (operArr[operArr.length - 1].matches("\\d+")) {
            throw new RuntimeException("逆波兰表达式有误,最后一位应该为操作符");
        }
        List list = new ArrayList();
        for (String str : operArr) {
            list.add(str);
        }
        return list;
    }

    //将中序表达式装入ArrayList中
    public static List toInfixExpersionList(String s) {
        if (s == "") {
            throw new RuntimeException("中序表达式不能为空!!");
        }
        int index = 0;//相当于一个指针用于遍历s
        char oper = ' ';//用于存储s中index索引处的字符
        List list = new ArrayList();
        String str = "";//用于处理多位数
        do {
            if ((oper = s.charAt(index)) < 48 || (oper = s.charAt(index)) > 57) {
                //当前字符是非数字
                list.add("" + oper);
                index++;
            } else {
                str = "";
                //当前字符为操作数,要判断是不是多位数
                while (index < s.length() && (oper = s.charAt(index)) >= 48 && (oper = s.charAt(index)) <= 57) {
                    str += oper;//拼接;
                    index++;
                }
                list.add(str);
            }

        } while (index < s.length());
        return list;
    }

    //得到操作符的优先级

    public static int getPriority(int ch) {
        if (ch == '+' || ch == '-') {
            return 0;
        } else if (ch == '*' || ch == '/') {
            return 1;
        } else {
            return -1;
        }


    }
}

你可能感兴趣的:(数据结构与算法)