【Java数据结构】栈和队列

栈(Stack)

栈的概念

        栈是一种特殊的线性表,只允许在一端进行插入和删除。栈遵循后进先出,分别在栈顶删除、栈底插入

栈的常用方法 

        栈的一些方法,例如:出栈、入栈、取栈顶元素、是否为空、栈中元素个数等;

模拟实现栈(数组实现)

知道这些方法,接下来我们来模拟实现一个栈:数组实现栈出栈入栈的复杂度都是O(1)。

        如果是单链表的话,用头插法入栈出栈的复杂度是O(1);用尾插法是实现入栈出栈都需要将链表全部访问一遍所以复杂度是O(n)。但如果是双链表的话,不管哪边插入都可以实现入栈出栈复杂度是O(1)。双链表是一个很好用的链表,以后的算法中会经常使用。

  • 栈的底层时数组,通过计数器比较栈中元素个数是否超过数组长度,再实现一个构造方法。
    private int elem[];
    private int size;
    public MyStack(){
        this.elem = new int[3];
    }
  •  接着实现入栈方法;大致的流程就是判断栈中元素是否满,满了则扩容,没满就将元素放到数组的栈顶中。
//栈中所开辟的数组是否满
    public boolean isFull(){
        if (elem.length == size){
            return true;
        }
        return false;
    }
    //增加元素(入栈)
    public int push(int data){
        if (isFull()){
            elem =Arrays.copyOf(elem,elem.length*2);
        }
        elem[size] = data;
        size++;
        return data;
    }
  • 出栈;出栈前还需要判断栈中是否为空,空栈就没有元素可以出栈,不是空就直接返回出栈的元素,并且计数器也要-1。 
 //判断栈是否为空
    public boolean isempty(){
        if (size == 0){
            return true;
        }else{
            return false;
        }
    }
    //减少元素(出栈)
    public int pop(){
        if(isempty()){
            return -1;
        }
        return elem[size--];
    }
  •  取出栈顶元素;取出前也需要判断栈中是否为空,不为空就返回栈顶元素。
 //取出栈顶元素
    public int peek(){
        if (isempty()){
            return -1;
        }
        return elem[size-1];
    }

队列(Queue)

队列的概念 

        队列是只允许一端插入,另一端删除的特殊线性表。也就是先进先出,分别再队尾插入,对头删除 。

 

        不同于栈的是,栈(Stack)是一个类,底层是顺序表(也可以用链表实现栈);而队列(Queue) 是一个接口,底层是链表。所以队列在实例化时必须实例化LinkedList的对象(LinkedList实现了Queue接口)。

public static void main(String[] args) {
    Queue<Integer> queue = new LinkedList<>();
    queue.offer(12);
    queue.offer(24);
    queue.poll();
    System.out.println(queue);//[24]
}
队列的常用方法 

        队列 的一些方法,例如:出队列、入队列、获取队头元素、是否为空、队列中元素个数等;

模拟实现队列
  • 先创建一个结点,通过结点实现入队出队
static class ListNode {
        private int val;
        private ListNode prev;
        private ListNode next;
        public ListNode (int val){
            this.val = val;
        }
    }
 private ListNode front;//队尾
 private ListNode rear;//队头
  •  入队;可以假设为头插法进入,详细分为第一次进入(直接将队头队尾等于这个新的结点)和往后进入(头插法进入)。
//入队 头插法
    public void offer(int data){
        ListNode node = new ListNode(data);
        if (isEmpty()){
            front = rear = node;
        }else{
            front.prev = node;
            node.next = front;
            front = node;
        }
    }
  • 出队;如果入队是头插,那么出队就是尾出,还要注意是否队列为空。 
public boolean isEmpty(){
        if (front == null){
            return true;
        }
        return false;
    }
    //出队 删除头结点
    public int poll(){
        if(isEmpty()){
            return -1;
        }
        int val = rear.val;
        if (front == rear){
            front = rear = null;
        }else{
            rear.prev.next = null;
            rear = rear.prev;
        }
        return val;
    }
  •  队中元素个数,以及遍历整个队列
//队列元素个数
    public int size(){
        ListNode cur = front;
        int count = 0;
        while (cur != null){
            count++;
            cur = cur.next;
        }
        return count;
    }
    //遍历
    public void display(){
        ListNode cur = front;
        while (cur != null){
            System.out.print(cur.val+"  ");
            cur = cur.next;
        }
        System.out.println();
    }

循环队列

        由于我们对队列的不断入队与出队,导致队中出现浪费许多空间,所以就有循环队列的由来。它通过浪费一个空间来检验队列是否可以继续进入,循环队列是数组实现的。

循环队列的原理其实挺简单的,主要抓住取模  ,明白原理就相对容易些。

模拟实现循环队列 

        需要注意的是加一时不是只加一而是加一后还要取模;减一也是不是只减一,还需要考虑下标为0时不能减一而是数组长度减一、其它情况直接减一即可。

class MyCircularQueue {
    private int elem[];
    private int front;
    private int rear;
    
    public MyCircularQueue(int k) {
        this.elem = new int[k+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 int Front() {
        return elem[front];
    }
    //获取队尾元素
    public int Rear() {
        int r = (rear == 0)?elem.length-1:rear-1;
        return elem[r];
    }
    //是否为空
    public boolean isEmpty() {
        if(front == rear){
            return true;
        }
        return false;
    }
    //是否为满
    public boolean isFull() {
        if ((rear+1)%elem.length == front){
            return true;
        }
        return false;
    }
}

双端队列(Deque)

        双端队列允许两端都可以进行入队和出队的队列。Deque是一个接口,也必须创建LinkedList的对象。

 栈和队列都可以使用这个接口

Deque<Integer> stack = new ArrayDeque<>();//双端队列的线性实现(数组)
Deque<Integer> queue = new LinkedList<>();//双端队列的链式实现

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

StarRocks元数据无法合并

一、先说结论 如果您的StarRocks版本在3.1.4及以下&#xff0c;并且使用了metadata_journal_skip_bad_journal_ids来跳过某个异常的journal&#xff0c;结果之后就出现了FE的元数据无法进行Checkpoint的现象&#xff0c;那么选择升级版本到3.1.4以上&#xff0c;就可以解决。 …

使用qrcode.vue生成当前网页的二维码(H5)

使用npm&#xff1a; npm install qrcode.vue 使用yarn&#xff1a; yarn add qrcode.vue package.json&#xff1a; 实现&#xff1a; <template><div class"code"><qrcode-vue :value"currentUrl" :size"size" render-as&…

【STM32】RTT-Studio中HAL库开发教程十:EC800M-4G模块使用

文章目录 一、简介二、模块测试三、OneNet物联网配置四、完整代码五、测试验证 一、简介 EC800M4G是一款4G模块&#xff0c;本次实验主要是进行互联网的测试&#xff0c;模块测试&#xff0c;以及如何配置ONENET设备的相关参数&#xff0c;以及使用STM32F4来测试模块的数据上报…

STM32完全学习——FATFS0.15移植SD卡

一、下载FATFS源码 大家都知道使用CubMAX可以很快的将&#xff0c;FATFS文件管理系统移植到单片机上&#xff0c;但是别的芯片没有这么好用的工具&#xff0c;就需要自己从官网下载源码进行移植。我们首先解决SD卡的驱动问题&#xff0c;然后再移植FATFS文件管理系统。 二、SD…

【知识】cuda检测GPU是否支持P2P通信及一些注意事项

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你&#xff0c;欢迎[点赞、收藏、关注]哦~ 代码流程 先检查所有GPU之间是否支持P2P通信&#xff1b;然后尝试启用GPU之间的P2P通信&#xff1b;再次检查所有GPU之间是否支持P2P通信。 test.cu&…

Mysql大数据量表分页查询性能优化

一、模拟场景 1、产品表t_product,数据量500万+ 2、未做任何优化前,cout查询时间大约4秒;LIMIT offset, count 时,offset 值较大时查询时间越久。 count查询 SELECT COUNT(*) AS total FROM t_product WHERE deleted = 0 AND tenant_id = 1 分页查询 SELECT * FROM t_…

go语言的成神之路-筑基篇-对文件的操作

目录 一、对文件的读写 Reader?接口 ?Writer接口 copy接口 bufio的使用 ioutil库? 二、cat命令 三、包 1. 包的声明 2. 导入包 3. 包的可见性 4. 包的初始化 5. 标准库包 6. 第三方包 ?7. 包的组织 8. 包的别名 9. 包的路径 10. 包的版本管理 四、go mo…

Qt 应用程序转换为服务

一、在 Windows 上将 Qt 应用程序转换为服务 方法1&#xff1a; 创建一个 Windows 服务应用程序&#xff1a; Windows 服务应用程序是一个没有用户界面的后台进程&#xff0c;通常由 Win32 Service 模板创建&#xff0c;或者直接编写 main() 函数以实现服务逻辑。 修改 Qt 应…

【HarmonyOS之旅】HarmonyOS概述(一)

目录 1 -> HarmonyOS简介 2 -> HarmonyOS发展历程 3 -> HarmonyOS技术特性 3.1 -> 硬件互助&#xff0c;资源共享 3.1.1 -> 分布式软总线 3.1.2 -> 分布式设备虚拟化 3.1.3 -> 分布式数据管理 3.1.4 -> 分布式任务调度 3.1.5 -> 分布式连接…

5、栈应用-表达式求值

本章内容使用上述栈结构函数&#xff0c;来完成表达式求值操作。 表达式例如&#xff1a;3*(7-2) 或者 (0-12)*((5-3)*32)/(22) 。 1、实现思路 a、建立OPTR&#xff08;运算符&#xff09;和OPND&#xff08;数字&#xff09;两个栈&#xff0c;后输入字符串以结束 b、自左向…

【软件】教务系统成绩提交工具使用步骤

【软件】教务系统成绩提交工具使用步骤 零、快速开始 安装 与大多数软件一样&#xff0c;安装步骤很简单&#xff0c;一直点击“下一步”即可快速完成安装&#xff0c;安装完成后&#xff0c;在桌面会有一个软件图标&#xff0c;双击即可打开软件主界面。 导入成绩到Excel中…

书签管理工具的使用技巧

分类与筛选技巧 多层级分类&#xff1a;创建多层级的文件夹结构&#xff0c;如先按大的主题分类&#xff0c;再在每个主题下细分小类。例如&#xff0c;先创建 “工作”“学习”“生活” 等大文件夹&#xff0c;在 “工作” 文件夹下再细分 “项目文档”“办公软件”“行业资讯…

如何安全获取股票实时数据API并在服务器运行?

以下是安全获取股票实时数据 API 并在服务器运行的方法&#xff1a; 选择合适的券商或交易平台 评估自身需求&#xff1a;明确自己的交易策略、交易品种、交易频率等需求&#xff0c;以及对 股票api 的功能、性能、稳定性等方面的要求。调研券商或平台&#xff1a;了解不同券商…

图像处理-Ch2-空间域的图像增强

Ch2 空间域的图像增强 文章目录 Ch2 空间域的图像增强Background灰度变换函数(Gray-level Transformation)对数变换(Logarithmic)幂律变换(Power-Law)分段线性变换函数(Piecewise-Linear)对比度拉伸(Contrast-Stretching)灰度级分层(Gray-level Slicing) 直方图处理(Histogram …

告别 Shuffle!深入探索 Spark 的 SPJ 技术

随着 Spark > 3.3&#xff08;在 3.4 中更加成熟&#xff09;中引入的存储分区连接&#xff08;Storage Partition Join&#xff0c;SPJ&#xff09;优化技术&#xff0c;您可以在不触发 Shuffle 的情况下对分区的数据源 V2 表执行连接操作&#xff08;当然&#xff0c;需要…

解决Springboot整合Shiro自定义SessionDAO+Redis管理会话,登录后不跳转首页

解决Springboot整合Shiro自定义SessionDAORedis管理会话&#xff0c;登录后不跳转首页 问题发现问题解决 问题发现 在Shiro框架中&#xff0c;SessionDAO的默认实现是MemorySessionDAO。它内部维护了一个ConcurrentMap来保存session数据&#xff0c;即将session数据缓存在内存…

【蓝桥杯——物联网设计与开发】基础模块8 - RTC

目录 一、RTC &#xff08;1&#xff09;资源介绍 &#x1f505;简介 &#x1f505;时钟与分频&#xff08;十分重要‼️&#xff09; &#xff08;2&#xff09;STM32CubeMX 软件配置 &#xff08;3&#xff09;代码编写 &#xff08;4&#xff09;实验现象 二、RTC接口…

API安全学习笔记

必要性 前后端分离已经成为web的一大趋势&#xff0c;通过TomcatNgnix(也可以中间有个Node.js)&#xff0c;有效地进行解耦。并且前后端分离会为以后的大型分布式架构、弹性计算架构、微服务架构、多端化服务&#xff08;多种客户端&#xff0c;例如&#xff1a;浏览器&#x…

2011-2020年各省城镇职工基本医疗保险年末参保人数数据

2011-2020年各省城镇职工基本医疗保险年末参保人数数据 1、时间&#xff1a;2011-2020年 2、来源&#xff1a;国家统计局 3、指标&#xff1a;省份、时间、城镇职工基本医疗保险年末参保人数 4、范围&#xff1a;31省 5、指标解释&#xff1a;参保人数指报告期末按国家有关…

【蓝桥杯——物联网设计与开发】拓展模块4 - 脉冲模块

目录 一、脉冲模块 &#xff08;1&#xff09;资源介绍 &#x1f505;原理图 &#x1f505;采集原理 &#xff08;2&#xff09;STM32CubeMX 软件配置 &#xff08;3&#xff09;代码编写 &#xff08;4&#xff09;实验现象 二、脉冲模块接口函数封装 三、踩坑日记 &a…