数据结构-4.栈与队列

news2024/11/24 13:36:21

本篇博客给大家带来的是栈和队列的知识点, 其中包括两道面试OJ题 用队列实现栈 和 用栈实现队列.

文章专栏: Java-数据结构

若有问题 评论区见

欢迎大家点赞 评论 收藏 分享

如果你不知道分享给谁,那就分享给薯条, 如果分享不成功, 那我就会回你一下,那样你就分享成功啦.

你们的支持是我不断创作的动力 .

1.栈(Stack)

1.1概念

栈: 一种特殊的线性表, 只许在固定的一端进行插入和删除元素操作. 进行数据插入和删除操作的一端称为栈顶, 另一端称为栈底. 栈中的数据元素遵守后进先出的原则.

在栈顶入数据称为压栈, 在栈顶出数据称为出栈.

1.2栈的使用

public static void main(String[] args) {
        Stack<Integer> stack = new Stack<>();
        stack.push(12);
        stack.push(23);
        stack.push(34);
        System.out.println(stack.size());//获取栈中有效元素个数-->4
        System.out.println(stack.peek());//获取栈顶元素-->4
        Integer x = stack.pop();//获取并删除栈顶元素
        System.out.println(x);
        System.out.println(stack.isEmpty());//判断栈是否为空.
    }

1.3 栈的模拟实现

Stack继承了Vector,  Vector 和 ArrayList 类似, 都是动态的顺序表, 不同的是Vector是线程安全的。

栈 是由 顺序表实现的,所以操作与顺序表大致相同.

public class MyStack {
    private int[] elem;
    private int usedSize;
    private static final int DEFAULT_CAPACITY = 10;

    public MyStack() {
        this.elem = new int[DEFAULT_CAPACITY];
    }

    //新增元素
    public void push(int val) {
        if(isFull()) {
            //空间不足,扩二倍.
            this.elem = Arrays.copyOf(this.elem, 2 * this.elem.length);
        }
        this.elem[usedSize] = val;
        usedSize++;
    }
    public boolean isFull() {
        return usedSize == elem.length;
    }

    public int pop() {
        if(isEmpty()) {
            System.out.println("栈为空");
            /*throw new EmptyException();*/
        }
        int OldVal = elem[usedSize-1];
        usedSize--;
        return OldVal;
    }

    public int peek() {
        if(isEmpty()) {
            System.out.println("栈为空");
            /*throw new EmptyException();*/
        }
        return elem[usedSize-1];
    }

    private boolean isEmpty() {
        return usedSize == 0;
    }
    
}

1.4栈的应用场景

1. 改变元素的序列

2. 将递归转化为循环

1.5概念区分

栈 , 虚拟机栈 , 栈帧有什么区别 ?

本章所学的栈为数据结构栈,  虚拟机栈是内存当中的一块区域.

每次调用方法都需要在栈上给方法开辟一块内存,这块内存就是栈帧.

2.队列(Queue)

2.1概念

队列: 只允许在一端进行插入数据操作, 在另一端进行删除数据操作的特殊线性表, 队列具有先进先出特性, 进行插入操作的一段称为队尾, 这一操作是入队列.进行删除操作的一端称为队头,这一操作称为出队列.

2.2队列的使用

在Java中,Queue是个接口, 底层是通过链表实现的.

public static void main(String[] args) {
        Queue<Integer> queue = new LinkedList<>();
        queue.offer(1);
        queue.offer(2);
        queue.offer(3);//从队尾入队列.

        System.out.println(queue.size());//队列长度
        System.out.println(queue.poll());//删除并返回队头元素
        System.out.println(queue.peek());//瞄一眼队头元素
        if(queue.isEmpty()) {
            System.out.println("队列为空");
        }else {
            System.out.println(queue.size());
        }
    }

2.3队列模拟实现


public class MyLinkedListQueue {
    class ListNode {
        ListNode prev;
        ListNode next;
        int val;

        public ListNode(int val) {
            this.val = val;
        }
    }
    ListNode head;
    ListNode last;
    private int usedSize = 0;
    //插入元素
    public void offer(int val) {
        ListNode node = new ListNode(val);
        if(isEtmpty()) {
            head = last = node;
            usedSize++;
        }else {
            last.next = node;
            node.prev = last;
            last = node;
            usedSize++;
        }
    }
    //删除队头节点并返回其元素值
    public int poll() {
        if(isEtmpty()) {
            return -1;
        }else {
            //只有一个节点
            if(head.next == null) {
                int ret1 = head.val;
                head = last = null;
                usedSize--;
                return ret1;
            }
            //两个节点及以上:
            int ret2 = head.val;
            head = head.next;
            head.prev = null;
            usedSize--;
            return ret2;
        }
    }

    //peek头节点的值
    public int peek() {
        if(isEtmpty()) {
            return -1;
        }else {
            return head.val;
        }
    }
    //得到数据个数
    public int getUsedSize() {
        return usedSize;
    }
    public boolean isEtmpty() {
        return usedSize == 0;
    }
}

2.4循环队列

实际中我们有时还会使用一种队列叫循环队列。如操作系统课程讲解生产者消费者模型时可以就会使用循环队列。 环形队列通常使用数组实现。
先来看循环队列怎么插入元素
队头和队尾都处于0下标处, 那么rear = front时,队列为空. 从0下标处开始插入元素.
当rear走到 7 下标时, rear 如果继续++, rear=8越界, 所以rear不能简单的++.   又想让rear回到0下标.  可以rear = (rear+1)%elem.length; 
 
622. 设计循环队列 - 力扣(LeetCode)按照上面的思路写一写这道OJ题, 答案如下:
class MyCircularQueue {

    private int[] elem;
    private int front;
    private int rear;
    public MyCircularQueue(int k) {
        this.elem = new int[k+1];
    }
    public int Front() {
        if(!isEmpty()) {
            return elem[front];
        }
        return -1;
    }
    public int Rear() {
        if(!isEmpty()) {
            int index = (rear == 0) ? elem.length - 1 : rear-1;
            return elem[index];
        }
        return -1;
    }
    public boolean enQueue(int value) {
        if(isFull()) {
            return false;
        }
        elem[rear] = value;
        rear = (rear+1)%elem.length;
        return true;
    }
    public boolean deQueue() {
        if(isEmpty()) {
            return false;
        }
        front = (front+1)%elem.length;
        return true;
    }
    //检查队列是否为空
    public boolean isEmpty() {
        return rear == front;
    }
    //检查队列是否已满
    public boolean isFull() {
        return (rear+1)%elem.length == front;
    }
}

3.栈与队列互相实现的OJ题

225. 用队列实现栈 - 力扣(LeetCode)

1. 入栈怎么入呢?定义两个队列qu1和qu2,  都为空默认入到qu1,  只有一个为空,就是哪个不为空入哪个, 都不为空入到qu1.

public void push(int x) {
        if(!qu1.isEmpty()) {
            qu1.offer(x);
        }else if(!qu2.isEmpty()) {
            qu2.offer(x);
        }else {
            qu1.offer(x);
        }
    }

2. 出栈怎么出呢?画图分析,不难得出实现栈至少需要两个队列.

两个队列怎么做到先出45呢?

执行上图操作后, 再出qu1队头元素,就做到了先出45. 

接着 如果要删除34也是一样的, 先把12和23在 qu2出队 到 qu1...

public int top() {
        if(empty()) {
            return -1;
        }
    
        if(!qu1.isEmpty()) {
            int tmp = 0;
            int size = qu1.size();
            for (int i = 0; i < size; i++) {
                tmp = qu1.poll();
                qu2.offer(tmp);
            }
            return tmp;
        }else {
            int size = qu2.size();
            int tmp1 = 0;
            for (int i = 0; i < size; i++) {
                tmp1 = qu2.poll();
                qu1.offer(tmp1);
            }
            return tmp1;
        }
    }
    public boolean empty() {
        return qu1.isEmpty() && qu2.isEmpty();
    }
}

整道题的答案 

class MyStack {

    private Queue<Integer> qu1;
    private Queue<Integer> qu2;
    public MyStack() {
        qu1 = new LinkedList<>();
        qu2 = new LinkedList<>();
    }
    public void push(int x) {
        if(!qu1.isEmpty()) {
            qu1.offer(x);
        }else if(!qu2.isEmpty()) {
            qu2.offer(x);
        }else {
            qu1.offer(x);
        }
    }
    public int pop() {
        if(empty()) {
            return -1;
        }
        if(!qu1.isEmpty()) {
            int size = qu1.size();
            for (int i = 0; i < size-1; i++) {
                int tmp = qu1.poll();
                qu2.offer(tmp);
            }
            return qu1.poll();
        }else {
            int size = qu2.size();
            for (int i = 0; i < size-1; i++) {
                int tmp = qu2.poll();
                qu1.offer(tmp);
            }
            return qu2.poll();
        }
    }
    public int top() {
        if(empty()) {
            return -1;
        }
    
        if(!qu1.isEmpty()) {
            int tmp = 0;
            int size = qu1.size();
            for (int i = 0; i < size; i++) {
                tmp = qu1.poll();
                qu2.offer(tmp);
            }
            return tmp;
        }else {
            int size = qu2.size();
            int tmp1 = 0;
            for (int i = 0; i < size; i++) {
                tmp1 = qu2.poll();
                qu1.offer(tmp1);
            }
            return tmp1;
        }
    }
    public boolean empty() {
        return qu1.isEmpty() && qu2.isEmpty();
    }
}

232. 用栈实现队列 - 力扣(LeetCode)

1. 入队, 将所有元素入到第一个栈中 s1.

2.出队, 把第一个栈中所有元素全部倒回第二个栈中, 出s2 的栈顶元素即可.

class MyQueue {

    Stack<Integer> s1;
    Stack<Integer> s2;
    public MyQueue() {
        s1 = new Stack<>();
        s2 = new Stack<>();
    }
    public void push(int x) {
        s1.push(x);
    }
    public int pop() {
        if(empty()) {
            return -1;
        }
        if(s2.empty()) {
            while(!s1.empty()) {
                s2.push(s1.pop());
            }
        }
        return s2.pop();
    }
    public int peek() {
        if(empty()) {
            return -1;
        }
        if(s2.empty()) {
            while(!s1.empty()) {
                s2.push(s1.pop());
            }
        }
        return s2.peek();
    }
    public boolean empty() {
        return s1.size() == 0 && s2.size() == 0;
    }
}

以上就是本文的全部内容了, 感谢观看!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2164276.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

在Unity编辑器中实现组件的复制与粘贴:完整指南

内容将会持续更新&#xff0c;有错误的地方欢迎指正&#xff0c;谢谢! 在Unity编辑器中实现组件的复制与粘贴&#xff1a;完整指南 TechX 坚持将创新的科技带给世界&#xff01; 拥有更好的学习体验 —— 不断努力&#xff0c;不断进步&#xff0c;不断探索 TechX —— 心…

低空经济——载具

低空经济的政策大家都知道&#xff0c;开放低空&#xff0c;是经济和社会发展的需要&#xff0c;但是步子肯定不会太大&#xff0c;先刺激资本进行投入&#xff0c;之后看看再说&#xff0c;一定是这样模式。 我们知道&#xff0c;新能源车&#xff0c;基本实现了弯道超车&…

基于springboot vue网上摄影工作室系统设计与实现

博主介绍&#xff1a;专注于Java vue .net php phython 小程序 等诸多技术领域和毕业项目实战、企业信息化系统建设&#xff0c;从业十五余年开发设计教学工作 ☆☆☆ 精彩专栏推荐订阅☆☆☆☆☆不然下次找不到哟 我的博客空间发布了1000毕设题目 方便大家学习使用 感兴趣的…

jni动态库“%1 不是有效的win32应用程序”问题的解决以及一些windows下dll有关命令的记录

一、前因 在windows下用cmakeVS编译了一个jni动态库&#xff0c;再使用java测试程序调用这个动态库的时候报错&#xff1a;“%1 不是有效的win32应用程序” 对于这类问题&#xff0c;一般从以下几个方面考虑&#xff1a; 动态库文件损坏动态库或者其依赖库文件路径错误导致找…

高效职场助手

在现代职场中&#xff0c;高效的工作软件是提升生产力的关键。以下是我为您精选的五款高效工作软件&#xff0c;它们各具特色&#xff0c;能够满足不同工作场景的需求&#xff1a; 1 亿可达 亿可达作为一款自动化工具&#xff0c;亿可达被誉为国内版的免费Zaiper。它允许用…

一个Windows管道的简单示例

今天为大家带来一个Windows管道通信的演示实例,服务端以单线程、同步方式与客户端通信,在某一时刻只能服务于一个客户端,可用于简单的进程间通信的场景。 服务端(SingleInstancePipeSvr)和客户端(NamedPipeClient)都是用Visual Studio 2022 Community创建,分别…

抖音上下边框中间视频效果怎么做

在抖音这个以短视频为主要内容的平台上&#xff0c;创作出既美观又富有信息量的视频至关重要。尤其是当我们手中的素材多为横屏拍摄&#xff0c;而抖音则以竖屏展示为主时&#xff0c;如何巧妙地处理这些素材&#xff0c;使它们更好地适应平台需求&#xff0c;成为了许多创作者…

Django之Haystack对接搜索引擎框架Elasticsearch

Django之Haystack对接Elasticsearch Haystack概述安装依赖环境准备Haystack配置 Haystack建立数据索引创建模型对象创建搜索索引类创建模板文件执行数据库迁移生成索引渲染模板执行测试 搜索请求和结果渲染的自定义处理概述创建搜索视图配置URL创建搜索模板自定义结果渲染执行测…

电脑数据怎么恢复?这10种数据恢复方法你一定要知道!

在如今这个数字化时代&#xff0c;电脑已经成为我们生活和工作中不可或缺的一部分。我们在电脑中存储着大量重要的数据&#xff0c;如照片、文档、视频、音乐等。然而&#xff0c;有时候意外总是不可避免&#xff0c;电脑数据可能会因为各种原因丢失&#xff0c;比如误删除、格…

父母血型与子女血型对照表

人类的血型是有遗传性的&#xff0c;父母的血型直接影响孩子的血型&#xff0c;我们可以根据父母血型推测孩子血型&#xff0c;排除不可能血型&#xff0c;那么下面就由血型分析为大家揭晓下父母血型与孩子血型对照表&#xff08;排除基因突变&#xff09; 血型遗传规律表又称血…

IMS注册流程中的基本路由寻址过程

目录 1. SIP 协议栈在 TCP/IP 中的位置 2. 看看 SIP 协议栈各层的寻址功能 本课程,以 IMS 注册流程为例,讲解 IP 网络网元是如何完成 IP 层寻址的 第一跳:UE->P-CSCF 第二跳:P-CSCF->DNS 第三跳:P-CSCF->I-CSCF 第四跳:I-CSCF->HSS 第五跳:I-CSCF-&…

深入解析Debian与Ubuntu:技术特点与用户使用指南

深入解析Debian与Ubuntu&#xff1a;技术特点与用户使用指南 引言 Debian和Ubuntu作为两大知名的Linux发行版&#xff0c;不仅在历史和理念上有所不同&#xff0c;在技术特点和用户使用方法上也各具特色。本文将深入解析它们的技术特点&#xff0c;并提供用户使用指南&#x…

SSM+Vue大学生社团管理系统

目录 1 项目介绍2 项目截图3 核心代码3.1 Controller3.2 Service3.3 Dao3.4 spring-mybatis.xml3.5 spring-mvc.xml3.5 Vue 4 数据库表设计5 文档参考6 计算机毕设选题推荐7 源码获取 1 项目介绍 博主个人介绍&#xff1a;CSDN认证博客专家&#xff0c;CSDN平台Java领域优质创作…

东华大学《2020年+2022年824自动控制原理真题》 (完整版)

本文内容&#xff0c;全部选自自动化考研联盟的&#xff1a;《25届东华大学824自控考研资料》的真题篇。后续会持续更新更多学校&#xff0c;更多年份的真题&#xff0c;记得关注哦~ 目录 2020年真题 2022年真题 Part1&#xff1a;2020年2022年完整版真题 2020年真题 2022年…

惊艳桌面时钟软件 为你的桌面打造专属时间管理!

在快节奏的现代生活中&#xff0c;时间是最宝贵的资源之一。无论是在工作还是生活中&#xff0c;我们都需要时刻关注时间&#xff0c;在桌面显示一个时钟&#xff0c;可以让你更方便的掌握时间。芝麻时钟 &#xff08;下载地址&#xff1a;https://clock.zhimasoft.cn/?bili&a…

Jmeter——参数化的9种方法

jmeter工具无论做接口测试还是性能测试&#xff0c;参数化都是一个必须掌握且非常有用的知识点。参数化的使用场景: 1&#xff09;多个请求都是同一个ip地址&#xff0c;若服务器地址更换了&#xff0c;则脚本需要更改每个请求的ip 2&#xff09;注册账号&#xff0c;不允许账…

【图形学】数学基础

行矩阵和列矩阵 在图形处理中&#xff0c;矩阵操作时最基本的操作&#xff0c;但是不同的系统中对矩阵的存储是不同&#xff0c;比如OpenGL和Cg中就是不一样的&#xff1a; 比如一个4x4矩阵 [m11,m12,m13,m14m21,m22,m23,m24m31,m32,m33,m34m41,m42,m43,m44]在实现中通常将其…

海康威视网络摄像头校时、修改分辨率等操作汇总!

目录 操作环境&#xff1a; 操作原因&#xff1a; 解决办法&#xff1a; 手动校准时间&#xff0c;随着时间推移&#xff0c;可能再次出现偏差&#xff0c;操作简单&#xff1a; 【IVMS-4200】对设备批量校时操作指导&#xff1a;操作之前先把本地服务器的时间改对&#x…

【学习笔记】Kylin-Desktop-V10-SP1 麒麟系统知识2——账户设置

提示&#xff1a;学习麒麟Kylin-Desktop-V10-SP1系统账户设置相关知识&#xff0c;包含用户名修改、用户密码修改、账户类型修改、开机自动登录、免密登录、添加用户、删除用户&#xff0c;以及修改登录选项相关知识 一、前期准备 成功安装麒麟系统&#xff08;本次实验的安装…

视频压缩成文件怎么弄?4招教会你

视频文件过大&#xff0c;不仅占用存储空间&#xff0c;还影响传输效率。但是&#xff0c;压缩视频时又担心会损失画质。有没有一种方法&#xff0c;能在不牺牲画质的前提下&#xff0c;实现视频文件的压缩呢&#xff1f;答案是肯定的。 想快速学会怎么视频压缩不改变清晰度&a…