数据结构-栈和队列刷题集(长期更新)

文章目录

万能计算器的实现以及源码分析

java 复制代码
/**
 * 我们尝试写一个完整版的计算器,由于计算机不能很好的识别括号,所以一般要转换为逆波兰表达式求解
 * 思路解析 :
 * 1. 输入一个 中缀表达式
 * 2. 中缀表达式转化为list存储
 * 3. 把list转换为一个逆波兰表达式
 *      规则如下 首先准备两个栈,stack1 , list2(stack2)
 *      如果是数字直接装入 list2
 *      如果是括号 分为左括号跟右括号
 *         如果是左括号直接进入stack1
 *         如果是右括号 stack1 弹栈 ,弹出的元素进入stack2,直到出现 ')' ,抵消掉一个右括号
 *      如果是操作符
 *          如果stack1 为空 或者是 栈顶为左括号,那么直接入栈          <---------------------------
 *          如果操作符的优先级大于 栈顶 操作符的优先级,直接入栈                                    *
 *          如果操作符的优先级小于等于 栈顶操作符 ,那么就弹出栈顶元素入stack2,然后进入第一条比较 --------
 *
 * 4. 利用逆波兰表达式进行求值
 */
class MyCalculator{
    public static void main(String[] args) {
        String s = "1+ ((2 +3) *4 )-5";
        List<String> infixexperssion = toList(s);
        List<String> suffixexpression = toSuffixexpression(infixexperssion);
        int ret = calculate(suffixexpression);
        System.out.println(ret);
    }

    /**
     * 该方法的作用就是把一个字符串转换为一个中缀表达式的list
     * @param infixexpression : 中缀表达式
     * @return
     */
    public static List<String> toList(String infixexpression){
        List<String> ret = new ArrayList<>();
        int count = 0;
        while(count < infixexpression.length()){
            if(infixexpression.charAt(count) == ' '){
                count++;
                continue;
            }
            if(infixexpression.charAt(count) < '0' || infixexpression.charAt(count) > '9'
                    && infixexpression.charAt(count)!=' '){
                ret.add(infixexpression.charAt(count) + "");
                count++;
            }else{
                StringBuilder stringBuilder = new StringBuilder();
                while(count < infixexpression.length() && infixexpression.charAt(count)>='0'
                        && infixexpression.charAt(count)<='9'){
                    stringBuilder.append(infixexpression.charAt(count));
                    count++;
                }
                ret.add(stringBuilder.toString());
            }
        }
        return ret;
    }


    /**
     * 该方法的作用是将我们的中缀表达式转化为逆波兰表达式
     * @param infixexpression : 传入的中缀表达式
     * @return
     */
    public static List<String> toSuffixexpression(List<String> infixexpression){
        //首先创建两个栈,因为第二个栈不涉及弹栈操作,所以我们可以创建为顺序表
        Stack<String> stack = new Stack<>();
        List<String> list = new ArrayList<>();

        for(String elem : infixexpression){
            if(elem.equals("(")){
                stack.push(elem);
            }else if(elem.equals(")")){
                while(stack.size() != 0 && !stack.peek().equals("(")){
                    list.add(stack.pop());
                }
                stack.pop();
            }else if(isOperator(elem) ){
                if(stack.size() == 0 || stack.peek().equals("(") || priority(elem) > priority(stack.peek())){
                    stack.push(elem);
                    continue;
                }
                while(stack.size() != 0 && priority(elem) <= priority(stack.peek()) && !stack.peek().equals("(")){
                    list.add(stack.pop());
                }
                stack.push(elem);
            }else{
                list.add(elem);
            }
        }
        while(stack.size() != 0){
            list.add(stack.pop());
        }
        return list;
    }

    //判断是否是操作符
    public static boolean isOperator(String elem){
        if(elem.equals("+")||elem.equals("-")||elem.equals("*")||elem.equals("/")){
            return true;
        }
        return false;
    }

    //判断优先级的大小
    public static int priority(String elem){
        if(elem.equals("+") || elem.equals("-")){
            return 1;
        }else{
            return 2;
        }
    }

    /**
     * 最后收一下尾巴,用我们所得到的逆波兰表达式求出值
     * 求值的基本思路应该比较好理解
     * 如果是数字直接入栈,如果不是,弹出两个数字,然后进行运算结果入栈
     */
    public static int calculate(List<String> sufferixexperssion){
        Stack<String> stack = new Stack<>();
        for(String elem : sufferixexperssion){
            if(isOperator(elem)){
                int num2 = Integer.parseInt(stack.pop());
                int num1 = Integer.parseInt(stack.pop());
                switch (elem){
                    case "+" :
                        stack.push((num1+num2)+"");
                        break;
                    case "-" :
                        stack.push((num1-num2)+"");
                        break;
                    case "*" :
                        stack.push((num1*num2)+"");
                        break;
                    case "/" :
                        stack.push((num1/num2)+"");
                        break;
                }
            }else{
                stack.push(elem);
            }
        }
        return Integer.parseInt(stack.pop());
    }
}

1. leetcode 150 逆波兰表达式求值

逆波兰表达式又叫做后缀表达式,因为计算机是好辨认出中缀表达式的计算顺序的,所以有时候要用后缀表达式进行求解

题目描述

思路分析:

1.如果是数字,直接入栈

2.如果是操作符,弹出两个数字分别作为右操作数跟左操作数运算,结果入栈

3.最后弹出栈内的最后一个元素

代码实现如下

java 复制代码
	public static int evalRPN(String[] tokens) {
        Stack<String> stack = new Stack<>();
        for (int i = 0; i < tokens.length; ++i) {
            String s = tokens[i];
            if (toolOperator(s)) {
                int num1 = Integer.parseInt(stack.pop());
                int num2 = Integer.parseInt(stack.pop());
                switch (s) {
                    case "+":
                        stack.push((num2 + num1) + "");
                        break;
                    case "-":
                        stack.push((num2 - num1) + "");
                        break;
                    case "*":
                        stack.push((num2 * num1) + "");
                        break;
                    case "/":
                        stack.push((num2 / num1) + "");
                        break;
                }
            } else {
                stack.push(s);
            }
        }
        return Integer.parseInt(stack.pop());
    }

    //判断是不是操作符
    public static boolean toolOperator(String s) {
        if (s.equals("+") || s.equals("-") || s.equals("*") || s.equals("/")) {
            return true;
        }
        return false;
    }
相关推荐
不染尘.5 分钟前
Linux磁盘分区和NAT网络配置
linux·运维·网络·windows·ssh
model20056 分钟前
alibaba linux3 定时下载任务未执行
linux·运维·服务器
盘古信息IMS19 分钟前
WMS 智能仓储管理系统推荐,如何搭建数智化时代的敏捷仓储平台
大数据·运维
nie_xl19 分钟前
VS/TRAE中设置本地maven地址的方法
运维·服务器·前端
Yupureki19 分钟前
《算法竞赛从入门到国奖》算法基础:入门篇-贪心算法(上)
c语言·数据结构·c++·算法·贪心算法·visual studio
散峰而望21 分钟前
【算法竞赛】队列和 queue
开发语言·数据结构·c++·算法·链表·github·线性回归
yuanmenghao25 分钟前
车载Linux 系统问题定位方法论与实战系列 - 开篇: 为什么需要一套“系统化”的 Linux 问题定位方法
linux·运维·服务器·数据结构·c++·自动驾驶
岁岁种桃花儿27 分钟前
深入理解 Keepalive:从协议到 Nginx 实战(全场景解析)
运维·nginx
CheungChunChiu27 分钟前
# Xorg 配置与 modesetting 驱动详解:从设备节点到显示旋转
android·linux·ubuntu·显示·xserver
柏木乃一28 分钟前
基础IO(上)
linux·服务器·c语言·c++·shell