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

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<String> list = transferArrayList(lastExpersion);
        //遍历list集合进行对应的计算操作
        int res = 0;
        res = calculator(list);
        System.out.println(lastExpersion + "=" + res);*/

        //中序转后序
        String expersion = "1+((2+3)*4)-5";
        List<String> infixExpersion = new ArrayList<>();
        infixExpersion = toInfixExpersionList(expersion);
        System.out.println("中缀表达式:"+infixExpersion);
        List<String> 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<String> parseSuffixExpersion(List<String> list) {
        Stack<String> s1 = new Stack<>();
        List<String> 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<String> list) {
        if (list == null) {
            throw new RuntimeException("集合为空");
        }
        Stack<String> 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<String> list = new ArrayList<String>();
        for (String str : operArr) {
            list.add(str);
        }
        return list;
    }

    //将中序表达式装入ArrayList中
    public static List<String> toInfixExpersionList(String s) {
        if (s == "") {
            throw new RuntimeException("中序表达式不能为空!!");
        }
        int index = 0;//相当于一个指针用于遍历s
        char oper = ' ';//用于存储s中index索引处的字符
        List<String> list = new ArrayList<String>();
        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;
        }


    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
可以使用递归的方式来实现先序和中序后序,具体实现代码如下: ```java public class Tree { private static class Node { private char value; private Node left; private Node right; public Node(char value) { this.value = value; } } public static String preInToPost(String preOrder, String inOrder) { if (preOrder == null || inOrder == null || preOrder.length() != inOrder.length()) { return null; } Node root = preInToPost(preOrder.toCharArray(), 0, preOrder.length() - 1, inOrder.toCharArray(), 0, inOrder.length() - 1); StringBuilder sb = new StringBuilder(); postOrder(root, sb); return sb.toString(); } private static Node preInToPost(char[] preOrder, int preStart, int preEnd, char[] inOrder, int inStart, int inEnd) { if (preStart > preEnd) { return null; } Node root = new Node(preOrder[preStart]); int index = findIndex(inOrder, inStart, inEnd, preOrder[preStart]); int leftSize = index - inStart; root.left = preInToPost(preOrder, preStart + 1, preStart + leftSize, inOrder, inStart, index - 1); root.right = preInToPost(preOrder, preStart + leftSize + 1, preEnd, inOrder, index + 1, inEnd); return root; } private static void postOrder(Node root, StringBuilder sb) { if (root == null) { return; } postOrder(root.left, sb); postOrder(root.right, sb); sb.append(root.value); } private static int findIndex(char[] arr, int start, int end, char target) { for (int i = start; i <= end; i++) { if (arr[i] == target) { return i; } } return -1; } public static void main(String[] args) { String preOrder = "ABDCEGF"; String inOrder = "DBAEGCF"; String postOrder = preInToPost(preOrder, inOrder); System.out.println(postOrder); // DCBGEFA } } ``` 该代码中使用了一个内部类 `Node` 表示二叉树的节点,`preInToPost` 方法用于递归构建二叉树,`postOrder` 方法用于递归遍历二叉树并输后序遍历序列,`findIndex` 方法用于查找中序遍历序列中某个元素的位置。最后在 `main` 方法中调用 `preInToPost` 方法并输结果。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值