美文网首页
中缀转后缀字符串表达式求值

中缀转后缀字符串表达式求值

作者: RalapHao | 来源:发表于2019-06-08 15:30 被阅读0次

    概念

    1. 前缀表达式(波兰表达式)
      运算符位于操作数前,右到左依次入栈
    2. 中缀表达式
      从左到右依次入栈,一般转为后缀表达式
    3. 后缀表达式(逆波兰表达式)
      运算符位于操作数后

    中缀转后缀(思路)

    1. 初始化俩个栈,运算符s1与存储中间结果栈S2
    2. 左到右扫描中缀表达式
    3. 遇到操作数,直接入S2
    4. 遇到运算符,比较与S1栈顶运算符优先级比较
      • 如果运算符栈为空,直接入栈
      • 如果优先级比S1栈顶优先级高,直接入栈
      • 否则将S1出栈到S2,再次跳转到第四步,进行比较
    5. 遇到括号
      • 左括号,直接入栈
      • 有括号,依次弹出,并入S2,直到遇到左括号
    6. 重复Step 2~5 直到到达表达式最右端
    7. 将S1有依次弹出,并压入S2
      8.S2中的元素依次弹出,逆序就是后缀表达式

    代码实现

    public class PolandExpression {
    
        public static void main(String[] args) {
            PolandExpression pe = new PolandExpression();
    //        List<String> mList = pe.middlePolandToList("(3+4)*5-6");
            List<String> mList = pe.middlePolandToList("4*5-8+60+8/2");
            System.out.println("中缀表达式 : " + mList);
            List<String> aList = pe.middleToAffter(mList);
            System.out.println("后缀表达式 : " + aList);
            pe.calculation(aList);
        }
        
        public List<String> middleToAffter(List<String> mStr) {
            List<String> aList = new ArrayList<>();
            Stack<String> operStack = new Stack<>();
            Stack<String> numStack = new Stack<>();
            int currIndex = 0;
            while (true) {
                if (currIndex > mStr.size() - 1) {
                    break;
                }
                String curStr = mStr.get(currIndex);
                if (strIsNum(curStr)) {
                    //数字直接入栈
                    numStack.push(curStr);
                } else {
                    if ("(".equals(curStr)) {
                        operStack.push(curStr);
                    } else if (")".equals(curStr)) {
    
                        while (true) {
                            String top = operStack.pop();
                            if ("(".equals(top)) {
                                break;
                            } else {
                                numStack.push(top);
                            }
                        }
                    } else {
                        if (operStack.isEmpty()) {
                            //字符栈为空,直接入栈
                            operStack.push(curStr);
                        } else if (compareChar(curStr.charAt(0), operStack.peek().charAt(0))) {
                            //字符优先级高于栈顶
                            operStack.push(curStr);
                        } else {
                            numStack.push(operStack.pop());
                            continue;
                        }
                    }
                }
                currIndex++;
            }
    
            while (true) {
                if (operStack.isEmpty()) {
                    break;
                } else {
                    numStack.push(operStack.pop());
                }
            }
    
            while (true) {
                if (numStack.isEmpty()) {
                    break;
                } else {
                    aList.add(numStack.pop());
                }
            }
    
            numStack.stream().forEach(str -> {
                aList.add(str);
            });
            for (int i = 0; i < aList.size() / 2; i++) {
                int size = aList.size();
                String m = aList.get(i);
                aList.set(i, aList.get(size - 1 - i));
                aList.set(size - 1 - i, m);
            }
            return aList;
    
        }
    
        public boolean strIsNum(String str) {
            return str.matches("\\d+");
        }
    
    
        /**
         * 中缀表达式转List
         */
        public List<String> middlePolandToList(String str) {
            List<String> list = new ArrayList<>();
            String num = "";
            for (int i = 0; i < str.length(); i++) {
                char curChar = str.charAt(i);
                if (!Character.isDigit(curChar)) {
                    list.add(Character.toString(curChar));
                } else {
                    if (i == str.length() - 1) {
                        list.add(Character.toString(curChar));
                    } else if (Character.isDigit(str.charAt(i + 1))) {
                        num += curChar;
                        continue;
                    } else {
                        num += curChar;
                        list.add(num);
                    }
                    num = "";
                }
            }
            return list;
        }
    
    
        public int cal(int num1, int num2, char oper) {
            int resul = 0;
            switch (oper) {
                case '*':
                    resul = num1 * num2;
                    break;
                case '-':
                    resul = num2 - num1;
                    break;
                case '+':
                    resul = num1 + num2;
                    break;
                case '/':
                    resul = num2 / num1;
                    break;
                default:
                    break;
            }
            return resul;
        }
    
        /**
         * 比较字符优先级
         */
        public boolean compareChar(char char1, char char2) {
    
            if (char2 == '(' || char2 == ')') {
                return true;
            }
    
            if (char1 == '*' || char1 == '/') {
                if (char2 == '+' || char2 == '-') {
                    return true;
                } else {
                    return false;
                }
            } else {
                return false;
            }
        }
        
        public void calculation(List<String> aList) {
            int curIndex = 0;
            Stack<String> stack = new Stack<>();
            while (true) {
                if (curIndex >= aList.size()) {
                    break;
                }
                String curStr = aList.get(curIndex);
                if (strIsNum(curStr)) {
                    stack.push(curStr);
                } else {
                    int num1 = Integer.parseInt(stack.pop());
                    int num2 = Integer.parseInt(stack.pop());
                    int cal = cal(num1, num2, curStr.charAt(0));
                    stack.push(cal + "");
                }
                curIndex++;
            }
            System.out.println(stack.pop());
        }
    }
    

    相关文章

      网友评论

          本文标题:中缀转后缀字符串表达式求值

          本文链接:https://www.haomeiwen.com/subject/gtuixctx.html