Java数据结构-队列

目录

  • 1. 队列概念
  • 2. 模拟实现队列
    • 2.1 链式队列
    • 2.2 循环队列
  • 3. 双端队列
  • 4. 队列的应用
    • 4.1 用队列实现栈
    • 4.2 用栈实现队列

1. 队列概念

队列是一种只能在一端进行插入数据操作,另一端进行删除数据操作的数据结构,插入数据的叫队尾,删除数据的叫队头。类似于生活中的排队打饭,进入队列中只能从队伍的后面进入,出队只能在队头出。队列是一种先进先出的数据结构。

2. 模拟实现队列

队列有链式结构和顺序结构两种,Java中的Queue接口底层是链式结构,包含方法如下:
在这里插入图片描述
add和offer表示入队,remove和poll表示出队,element和peek表示获取队头的元素(不删除)。

2.1 链式队列

Java的Queue底层是用双向链表实现的,所以我们也用双向链表模拟实现

public class MyQueue<E> {

    //使用双向链表
    static class ListNode {
        public ListNode next;//前驱
        public ListNode prev;//后继
        public Object val;//值

        //构造方法用于初始化
        public ListNode(Object val) {
            this.val = val;
        }
    }

    public ListNode head;//头
    public ListNode tail;//尾

    //入队->只能从尾部入队(尾插)
    public void offer(E val) {
        ListNode newNode = new ListNode(val);
        //第一次入队
        if (tail == null) {
            head = tail = newNode;
            return;
        }
        tail.next = newNode;
        newNode.prev = tail;
        tail = newNode;
    }

    //出队->只能从头部出队(头删)
    public E poll() {
        if (empty()) {
            return null;
        }
        Object ret = head.val;

        head = head.next;
        head.prev = null;
        return (E) ret;
    }

    //获取队头元素
    public E peek() {
        if (empty()) {
            return null;
        }
        return (E)head.val;
    }

    //判断队列是否为空
    public boolean empty() {
        return head == null;
    }

}

2.2 循环队列

循环队列是使用数组实现的,循环队列的结果如图
在这里插入图片描述
循环队列的原理: 循环队列看似乎结果成环,其实底层是连续的数组,实现循环的是队头(front)和队尾(rear)两个变量,front下标表示队列的第一个元素,rear下标则是队尾的下一个位置。队列为空的条件:front==rear,队列满了的条件:(rear+1)%数组长度 ==front
在这里插入图片描述

代码实现:

public class round_robinQueue<E> {
    public Object[] elem;//数组
    public int front;//队头
    public int rear;//队尾

	//k表示容量
    public round_robinQueue(int k) {
        this.elem = new Object[k + 1];//浪费一个空间,所以申请了k+1个空间
    }

    //入队一个元素
    public boolean offer(int value) {
        //满了不能插
        if (isFull()) {
            return false;
        }
        elem[rear] = value;
        rear = (rear + 1) % elem.length;
        return true;
    }

    //出队一个元素
    public boolean poll() {
        if (isEmpty()) {
            return false;
        }
        front = (front + 1) % elem.length;
        return true;
    }

    //获取队头元素
    public E getFront() {
        if (isEmpty()) {
            return null;
        }
        return (E) elem[front];
    }

    //获取队尾元素
    public E Rear() {
        if (isEmpty()) {
            return null;
        }
        //rear指向的是下一个位置,不是最后一个元素,如果rear=0,会越界
        if (rear == 0) {
            return (E) elem[elem.length - 1];
        }
        return (E) elem[rear - 1];
    }

    public boolean isEmpty() {
        return front == rear;
    }

    public boolean isFull() {
        return (rear + 1) % elem.length == front;
    }
}

3. 双端队列

双端队列指允许两端都可以进行入队、出队操作的队列,Java中可以使用Deque这个接口,有顺序实现ArrayDeque和链式实现LinkedList

4. 队列的应用

4.1 用队列实现栈

在这里插入图片描述

题目链接:用队列实现栈
解题思路: 首先,只使用一个队列是不行的,需要两队列。
实现逻辑: 入栈操作:将元素放入不为空的队列(如果是第一次入栈,两个队列都可以)。出栈操作:将不为空的队列中的n-1个元素放入另一个队列中,最后将剩下的元素出队。获取栈顶元素:将不为空的队列中所有的元素放入另一个队列中,返回最后一个元素即可
代码:

class MyStack {

    public Queue<Integer> q1;
    public Queue<Integer> q2;

    public MyStack() {
        q1 = new LinkedList<>();
        q2 = new LinkedList<>();
    }

    //入栈
    public void push(int x) {
        //如果都为空,在q1中添加
        if (empty()) {
            q1.offer(x);
            return;
        }
        if (q1.isEmpty()) {
            q2.offer(x);
        } else {
            q1.offer(x);
        }
    }

    //出栈
    public int pop() {
        //如果模拟栈为空,返回
        if (empty()) {
            return -1;
        }
        if (!q1.isEmpty()) {
            //q1不为空
            int size = q1.size();
            for (int i = 0; i < size - 1; i++) {
                q2.offer(q1.poll());
            }
            return q1.poll();
        } else {
            int size = q2.size();
            for (int i = 0; i < size - 1; i++) {
                q1.offer(q2.poll());
            }
            return q2.poll();
        }
    }

    //获取栈顶元素
public int top() {
        //如果模拟栈为空,返回
        if (empty()) {
            return -1;
        }
        if (!q1.isEmpty()) {
            //q1不为空
            int size = q1.size();
            int ret = -1;
            for (int i = 0; i < size; i++) {
                ret = q1.poll();
                q2.offer(ret);
            }
            return ret;
        } else {
            int size = q2.size();
            int ret = -1;
            for (int i = 0; i < size; i++) {
                ret = q2.poll();
                q1.offer(ret);
            }
            return ret;
        }
    }

    //判断模拟栈是否为空,如果两个队列都为空则为空
    public boolean empty() {
        return q1.isEmpty() && q2.isEmpty();
    }
}

4.2 用栈实现队列

在这里插入图片描述
题目链接: 用栈实现队列
解题思路: 使用两个栈实现队列,入队和出队的逻辑:其中一个栈(s1)只进行入栈操作,表示入队列;另一个栈(s2)只进行出栈操作,表示出队,如果s2空了再将s1中所有元素都入s2这个栈

代码:

class MyQueue {

    public Stack<Integer> s1;
    public 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;
        }
        //如果s2为空,把s1的所有元素拿过来
        if (s2.empty()) {
            while (!s1.empty()) {
                s2.push(s1.pop());
            }
        }
        return s2.pop();
    }

    public int peek() {
        if (empty()) {
            return -1;
        }
        //如果s2为空,把s1的所有元素拿过来
        if (s2.empty()) {
            while (!s1.empty()) {
                s2.push(s1.pop());
            }
        }
        return s2.peek();
    }

    public boolean empty() {
        return s1.empty() && s2.empty();
    }
}

今天的内容就到这里,感谢老铁们的点赞、收藏、评论~❤

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

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

相关文章

Vulnhub:BOSSPLAYERSCTF: 1

目录 信息收集 arp nmap nikto whatweb WEB web信息收集 dirmap 命令执行漏洞 反弹shell 提权 系统信息收集 get root 信息收集 arp ┌──(root㉿ru)-[~/kali/vulnhub] └─# arp-scan -l Interface: eth0, type: EN10MB, MAC: 00:50:56:2f:dd:9…

我与C++的爱恋:内联函数,auto

​ ​ &#x1f525;个人主页&#xff1a;guoguoqiang. &#x1f525;专栏&#xff1a;我与C的爱恋 ​ 一、内联函数 1.内联函数的概念 内联函数目的是减少函数调用的开销&#xff0c;通过将每个调用点将函数展开来实现。这种方法仅适用于那些函数体小、调用频繁的函数。 …

探索大数据时代下与云计算技术融合:实现企业级数据处理与分析的灵活性和效率性

引言&#xff1a; 关联阅读博客文章&#xff1a;深度剖析&#xff1a;计算机集群在大数据体系中的关键角色和技术要点 随着信息时代的到来&#xff0c;数据量的爆炸性增长已成为一种常态。企业、政府、科研机构等各个领域都面临着海量数据的收集、存储、处理和分析的挑战。在…

2024年福建三支一扶报名指南—照片<100kb

2024年福建三支一扶报名指南—照片<100kb

大日志精选案例四:某省级大数据集团日志审计优化实战解析

“在集团日常运营中&#xff0c;数据安全始终是我们关注的重点。过去&#xff0c;数据量大、处理速度慢&#xff0c;导致日志数据难以迅速获取和分析&#xff0c;影响业务决策。但自从引入聚铭大日志解决方案后&#xff0c;系统日志和用户行为数据都得到了高效处理与存储。该方…

C易错注意之分支循环,悬空else,短路表达式,static

接下来的日子会顺顺利利&#xff0c;万事胜意&#xff0c;生活明朗-----------林辞忧 前言&#xff1a; c语言中一些关于分支循环中continue常混淆&#xff0c;悬空esle问题&#xff0c;短路表达式&#xff0c;static ,extern在使用时稍不注意就会出错的点,接下来我们将介绍…

数据结构:排序

排序的概念 1.概念 就我当前所认识的排序来说。排序是把一串相同类型的数据&#xff0c;按照升序或者降序排列起来的操作。 以下介绍的排序大多可以排列不限于整型和文件&#xff0c;但也有一些算法有较明显的局限性。 2.稳定性 如果在排列之前&#xff0c;一组数据中&…

Airtable、pyairtable

文章目录 一、关于 AirtableAirtable 公司历史诞生发展 产品方向产品层级国内模仿者竞争对手关于 API Key价格 二、关于 pyairtable安装快速使用 一、关于 Airtable 官网&#xff1a;https://www.airtable.comgithub : https://github.com/AirtableAirtable AI &#xff1a; h…

搜索最短路/最小步数问题

文章目录 搜索专题之最短路/最小步数迷宫问题【题目描述】【输入样例】【输出样例】【AC代码】 武士风度的牛【题目描述】【AC代码】 抓住那头牛【题目描述】【AC代码】 魔板【题目描述】【AC代码】 搜索专题之最短路/最小步数 迷宫问题 【题目描述】 【输入样例】 5 0 1 0 …

【Clang+LLVM+honggfuzz学习】(一)LLVM简介、安装和第一个Hello Pass

本文结构&#xff0c;PS:根据需要选择观看哦 1. 前言参考 2.简介传统编译器架构LLVM架构 3. LLVM安装版本准备官网源码下载git下载安装过程 4. 写一个LLVM Pass旧Hello Pass实现&#xff08;legacy PM version&#xff09;新Hello Pass实现&#xff08;Using the New Pass Mana…

GPT4不限制使用次数了!GPT5即将推出了!

今天登录到ChatGPT Plus账户&#xff0c;出现了如下提示&#xff1a; 已经没有了数量和时间限制的提示。 更改前&#xff1a;每 3 小时限制 40 次&#xff08;团队计划为 100 次&#xff09;&#xff1b;更改后&#xff1a;可能会应用使用限制。 GPT-4放开限制 身边订阅了Ch…

【C++STL详解 —— vector的介绍及使用】

【CSTL详解 —— vector的介绍及使用】 vector的介绍vector的使用vector的构造vector iterator 的使用begin和endrbegin和rend vector 空间增长问题size和capacityreserve和resizeempty vector 增删查改push_back和pop_backinsert和erasefindswap元素访问 vector 迭代器失效问题…

Vue 如何快速上手

目录 1. Vue 是什么 &#xff08;概念&#xff09; 1.1. Vue 的两种使用方式 1.2. 优点 1.3. 缺点 2. 创建 Vue 实例&#xff0c;初始化渲染 2.1. 步骤&#xff08;核心步骤 4步&#xff09; 2.2. 练习——创建一个Vue实例 3. 插值表达式 {{ }} 3.1. 介绍 3.2. 作用…

哈哈哈哈哈

欢迎使用Markdown编辑器 你好&#xff01; 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章&#xff0c;了解一下Markdown的基本语法知识。 222 我们对Markdown编辑器进行了一些功能拓展与语法支持&#xff0c;…

大创项目推荐 深度学习 python opencv 火焰检测识别

文章目录 0 前言1 基于YOLO的火焰检测与识别2 课题背景3 卷积神经网络3.1 卷积层3.2 池化层3.3 激活函数&#xff1a;3.4 全连接层3.5 使用tensorflow中keras模块实现卷积神经网络 4 YOLOV54.1 网络架构图4.2 输入端4.3 基准网络4.4 Neck网络4.5 Head输出层 5 数据集准备5.1 数…

文件管理--fscanf,fread,fwrite和fprintf

fprintf函数&#xff1a;对于fprintf函数&#xff0c;它和printf一样&#xff0c;但是它的表达式为&#xff1a;int fprintf ( FILE * stream, const char * format, ... );和printf的很相似&#xff0c;但有不一样。它是格式化输出函数&#xff0c;代码为&#xff1a; #includ…

模拟退火遗传算法GASA-附MATLAB代码

模拟退火遗传算法&#xff08;Simulated Annealing Genetic Algorithm&#xff0c;SAGA&#xff09;结合了模拟退火算法&#xff08;Simulated Annealing&#xff0c;SA&#xff09;和遗传算法&#xff08;Genetic Algorithm&#xff0c;GA&#xff09;的优点&#xff0c;用于解…

数字化导师坚鹏:招商银行数字化转型的4次模式升级与5大关键举措

招商银行数字化转型的4次模式升级与5大关键举措 招商银行数字化转型取得了较大的成功&#xff0c;从目前的财务数据来看&#xff0c;招商银行在数字化转型领域已经成为国内最优秀的股份制银行。招商银行是如何取得数字化转型成功的&#xff1f;从招商银行数字化转型的4次模式升…

先进电气技术 —— 控制理论之控制与扰动的战争

一、与扰动的斗争催生控制理论 在控制理论中&#xff0c;可以说“Identification&#xff08;辨识&#xff09;”、“Observe&#xff08;观测&#xff09;”、“Estimate&#xff08;估计&#xff09;”和“Control&#xff08;控制&#xff09;”这四个核心概念都是为了“消…

Centos7安装Docker与Docker-compose【图文教程】

个人记录 查看一下系统是否已经安装了Docker yum list installed | grep docker如下图代表没有安装Docker 卸载已有Docker yum remove docker docker-common docker-selinux docker-engine切换目录 cd /etc/yum.repos.d/查看当前目录所有的镜像源 ll安装yum-util与devi…