数据结构之(三):队列

队列初体验之数组实现方式

队列
1 、初识队列
队列,是一种对存取有严格要求的数据结构
只能从尾部存入数据,从头部取出数据
遵循 先进先出 原则
队列的实现有两种方式:
顺序队列(基于数组)、链队列(基于链表)

 用数组实现队列

public class ArrayQueue {
    // 最大容量
    int maxCapacity;
    // 声明头尾指针
    int head;
    int tail;
    // 存储元素
    int[] arr;
    public ArrayQueue(int maxCapacity) {
        arr = new int[maxCapacity];
        maxCapacity = maxCapacity;
        head = 0;
        tail = 0;
    }
    public boolean isFull() {
        return tail == maxCapacity;
    }
    public void add(int n) {
// 先判断队列的容量大小
        if (!isFull()) {
            arr[tail] = n;
        }
    }
    public boolean isEmpty() {
        return head == tail;
    }
    public int get() {
// 先判断队列是否为空
        if (isEmpty()) return -1;
        int result = arr[head];
        head++;
        return result;
    }
}
LinkedList 的使用
    public static void main(String[] args) {
        Queue<Integer> queue = new LinkedList<>();
// 都能添加元素
// queue.add(1);
        queue.offer(1);
        queue.offer(2);
        queue.offer(3);
// 两者区别 当队列满的时候 add会抛出异常 offer会返回false 更健壮更友好
// 取出元素 分为两种
// 只获取队头元素 不取出
        queue.peek();
        queue.element();
// 两者区别 当队列为空时 element会抛出异常 peek会返回null
// 获取队头元素 同时取出
        queue.poll();
        queue.remove();
// 两者区别 当队列为空时 remove会抛出异常 poll会返回null
    }
链队列原理分析

 双端队列和各式队列

双端队列
双端队列,区别于普通队列
两端都可以进行入队和出队
deque = "double ended queue"
LinkedList ArrayDeque

 【特别的队列】

1 ) 优先级队列
元素携带了相关的优先级,优先级更高的元素排在头部
PriorityQueue ,提供了 Comparable 接口,元素可以实现其方法,改变在队列中的顺序
2 )阻塞队列
当队列满的时候,等待有空余位置再存数据;当队列空的时候,等待有新数据再读取
BlockingQueue put() take() 提供了存取的阻塞逻辑
分为两种情况,一种是无限期的等,一种是指定阻塞时间
3 )延迟队列
在指定时间内获取队列元素,头部元素是最接近过期时间的。
DelayQueue 给定一个接口设置延迟时间 元素会按照时间排序
挑战升级之队列的最大值
队列的最大值
https://leetcode-cn.com/problems/dui-lie-de-zui-da-zhi-lcof/
剑指 Offffer 59 - II. 队列的最大值
请定义一个队列并实现函数 max_value
得到队列里的最大值,要求函数 max_value push_back pop_front 的均摊时间复杂度都是
O(1)
若队列为空, pop_front max_value 需要返回 -1
示例 1
输入 :
["MaxQueue","push_back","push_back","max_value","pop_front","max_value"]
[[],[1],[2],[],[],[]]
输出 : [null,null,null,2,1,2]
分别对应 方法名、参数 以及 返回结果
示例 2
输入 :
["MaxQueue","pop_front","max_value"]
[[],[],[]]
输出 : [null,-1,-1]
分析:
队头 队尾
[1,2,3,4,3,2,1]
在队列发生更改时 记录出最大值
[] -1
[1] 1
[1,2] 2
[1,2,3] 3
[2,3] 3
[2,3,2,1] 3
[3,2,1] 3
[2,1] 2
因为增删操作时 都可能影响最大值的变化
如果是新增操作,比较新元素和当前最大值之间,更大的值是新的最大值
如果是删除操作,删除的元素如果不是最大值,那么最大值不变,如果是最大值,最大值要更改为剩余
元素的最大值
使用额外的队列,来记录最大值发生的变化
max 队列,队头元素是当前的最大值,而其他元素是未来可能成为最大值的候选值
新增元素 ele ele>max 取队列中队尾元素比较,如果满足,进行覆盖并且循环比较
直到把所有比它小的值都覆盖为止
ele<max 将其存到 max 队列中
原队列 max 队列
[1] [1]
[1,2] [2]
[1,2,3] [3]
[2,3] [3]
[2,3,2] [3,2]
[2,3,2,1] [3,2,1]
[3,2,1] [3,2,1]
[2,1] [2,1]
[2,1,4] [4]
public class MaxQueue {
    // 原始队列
    LinkedList<Integer> queue;
    // 最大值的候选值
    LinkedList<Integer> max;
    public MaxQueue() {
        queue = new LinkedList<>();
        max = new LinkedList<>();
    }
    public int max_value() {
        if (max.isEmpty()) return -1;
        return max.peekFirst();
    }
    // 新增元素 ele时 ele>max 取队列中队尾元素比较,如果满足,进行覆盖并且循环比较
// 直到把所有比它小的值都覆盖为止
// ele<max 将其存到max队列中
    public void push_back(int value) {
        queue.offer(value);
        while (!max.isEmpty() && max.peekLast() < value) {
            max.pollLast();
        }
        max.add(value);
    }
    public int pop_front() {
// 如果删除的元素是最大值 从max队列中同时删掉
        if (!max.isEmpty() && queue.peekFirst().equals(max.peekFirst())) {
            max.pollFirst();
        }
        if (queue.isEmpty()) return -1;
        return queue.poll();
    }
}
经典算法思想之滑动窗口
https://leetcode-cn.com/problems/hua-dong-chuang-kou-de-zui-da-zhi-lcof/
剑指 Offffer 59 - I. 滑动窗口的最大值
给定一个数组 nums 和滑动窗口的大小 k ,请找出所有滑动窗口里的最大值。
示例 :
输入 : nums = [1,3,-1,-3,5,3,6,7], k = 3
输出 : [3,3,5,5,6,7]
解释 :
滑动窗口的位置 最大值
[1 3 -1] -3 5 3 6 7 3
1 [3 -1 -3] 5 3 6 7 3
1 3 [-1 -3 5] 3 6 7 5
1 3 -1 [-3 5 3] 6 7 5
1 3 -1 -3 [5 3 6] 7 6
1 3 -1 -3 5 [3 6 7] 7
分析:
数组的长度为 n 窗口的大小为 k 可形成的窗口个数 n-k+1
通过队列来记录最大值
窗口未形成的阶段
遍历数组,同时更新队列
窗口已形成的阶段
每次窗口移动,都是在头部移除元素,尾部增加元素
在窗口变化过程中 记录其最大值的变化 ( 让最大值一直出现在第一位 )
让队列中已存在的元素 和新添加的元素比较 如果已存在的更小 那么覆盖
如果已存在的更大 新添加的元素是候选 缀到队列之后
滑动窗口的位置 最大值
滑动窗口的位置     最大值

[1 3 -1] -3 5 3 6 7    3
1 [3 -1 -3] 5 3 6 7    3
1 3 [-1 -3 5] 3 6 7    5
1 3 -1 [-3 5 3] 6 7    5
1 3 -1 -3 [5 3 6] 7    6
1 3 -1 -3 5 [3 6 7]    7
    窗口              max 队列
[1 3 -1]      [1] -> [3] -> [3,-1]
[3 -1 -3]     [3,-1,-3]
[-1 -3 5]     [-1,-3] -> [5]
[-3 5 3]      [5,3]
[5 3 6]       [6]
[3 6 7]        [7]
public static int[] maxSlidingWindow(int[] nums, int k) {
// 记录每个窗口的最大值 n-k+1为形成的窗口个数
        int[] result = new int[nums.length - k + 1];
// 使用队列记录最大值的候选值
        Deque<Integer> deque = new ArrayDeque<>();
// 窗口未形成的阶段
        for (int i = 0; i < k; i++) {
            print(deque);
// 每次都取 队尾元素和新元素 比较 如果队尾更小 删除
            while (!deque.isEmpty() && deque.peekLast() < nums[i]){
                deque.pollLast();
            }
            deque.offerLast(nums[i]);
        }
// 此时第一个窗口形成 deque的队头元素就是第一个窗口的最大值
        result[0] = deque.peekFirst();
        print(deque);
// 窗口已形成的阶段
        for (int i = k; i < nums.length; i++) {
            System.out.println("-----第" + (i-k+1) + "次滑动");
// 删了元素 nums[i-k] 添了元素 nums[i]
            if(nums[i-k] == deque.peekFirst()){
// 如果删的是最大值 同时从deque移除
                deque.pollFirst();
            }
// 新增
            while (!deque.isEmpty() && deque.peekLast() < nums[i]){
                deque.pollLast();
            }
            deque.offerLast(nums[i]);
            result[i-k+1] = deque.peekFirst();
            print(deque);
        }
        return result;
    }
    public static void print(Deque<Integer> deque){
        for (Integer integer : deque) {
            System.out.print(integer + " ");
        }
        System.out.println();
    }
}
循环队列的设计和实现
循环队列
循环队列
为解决,队列存取数据后,空间无法重复利用的问题,通过构造环形,重复使用
https://leetcode-cn.com/problems/design-circular-queue/
622. 设计循环队列
设计你的循环队列实现。 循环队列是一种线性数据结构,其操作表现基于 FIFO (先进先
出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为 环形缓冲器
循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普通队列里,一旦一个队
列满了,我们就不能插入下一个元素,即使在队列前面仍有空间。但是使用循环队列,我们能使
用这些空间去存储新的值。
你的实现应该支持如下操作:
MyCircularQueue(k): 构造器,设置队列长度为 k
Front: 从队首获取元素。如果队列为空,返回 -1
Rear: 获取队尾元素。如果队列为空,返回 -1
enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。
deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。
isEmpty(): 检查循环队列是否为空。
isFull(): 检查循环队列是否已满。

public class MyCircularQueue {
    // 存储元素的数组
    int[] queue;
    // 最大容量
    int capacity;
    // 头指针
    int head;
    // 实际队列长度
    int count;
    /**
     * Initialize your data structure here. Set the size of the queue to be k.
     */
    public MyCircularQueue(int k) {
        capacity = k;
        queue = new int[k];
        head = 0;
        count = 0;
    }
    /**
     * Insert an element into the circular queue. Return true if the operation
     is successful.
     */
    public boolean enQueue(int value) {
        if (isFull()) return false;
        int index = (head + count) % capacity;
        queue[index] = value;
        count++;
        return true;
    }
    /**
     * Delete an element from the circular queue. Return true if the operation
     is successful.
     */
    public boolean deQueue() {
        if (isEmpty()) return false;
        head = (head + 1) % capacity;
        count--;
        return true;
    }
    /**
     * Get the front item from the queue.
     */
    public int Front() {
        if (isEmpty()) return -1;
        return queue[head];
    }
    /**
     * Get the last item from the queue.
     */
    public int Rear() {
        if (isEmpty()) return -1;
        int tail = (head + count - 1) % capacity;
        return queue[tail];
    }
    /**
     * Checks whether the circular queue is empty or not.
     */
    public boolean isEmpty() {
        return count == 0;
    }
    /**
     * Checks whether the circular queue is full or not.
     */
    public boolean isFull() {
        return count == capacity;
    }
}


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

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

相关文章

4年功能测试月薪9.5K,3个月时间成功进阶自动化,跳槽涨薪6k后我的路还很长...

前言 其实最开始我并不是互联网从业者&#xff0c;是经历了一场六个月的培训才入的行&#xff0c;这个经历仿佛就是一个遮羞布&#xff0c;不能让任何人知道&#xff0c;就算有面试的时候被问到你是不是被培训的&#xff0c;我还是不能承认这段历史。我是为了生存&#xff0c;…

知识图谱实战(03):python操作neo4j实战

Python操作Neo4j例子&#xff08;官方版本&#xff09; Neo4j的Python版本驱动 Neo4j 提供了一个Python版本的驱动包&#xff0c;用来连接Neo4j数据库&#xff0c;从而完成图数据库的增删改查操作。 1、安装指定版本的驱动包&#xff08;我们这里采用Neo4.x版本&#xff0c;同n…

java微服务架构---hello world

本教程我们会使用IntelliJ IDEA&#xff08;以下简称IDEA&#xff09;进行学习。它是Java语言开发的集成环境&#xff0c;是业界公认的目前用于Java程序开发最好的工具&#xff0c;在代码错误提醒&#xff0c;智能代码补全等多方面表现都非常优秀&#xff0c;也是Java开发企业级…

KNN机器算法入门【Python】:实现手写数字识别

人生苦短&#xff0c;我用python KNN 可以说是最简单的分类算法之一 同时&#xff0c;它也是最常用的分类算法之一。 注意&#xff1a;KNN 算法是有监督学习中的分类算法&#xff0c;它看起来和另一个机器学习算法 K-means 有点像&#xff08;K-means 是无监督学习算法&#x…

不联网新华字典

介绍 首页字典 更多 包含内容 内容对应Json数据文件百家姓baijiaxing.json曹操诗集caocao.json弟子规dizigui.json成语idiom.json论语lunyu.json纳兰性德诗集nalanshiji.json千家诗qianjiashi.json千字文qianziwen.json三字经-传统版sanzijing_ct.json三字经-新版sanzijing_x…

【docker-compose】安装 Harbor

目录 一、环境 二、安装Harbor 1. 下载官网部署包&#xff08;本章使用版本 V2.7.1&#xff09; 2. 将部署包上传至服务器&#xff0c;并解压 3. 创建data目录 4. 复制 harbor.yml 5. 修改harbor.yml 6. 进行本地安装 7. docker-compose 安装组件 8. ip:port 访问 三…

【软考五】数据库(做题)

该文章不适合学习数据库&#xff0c;适合考证&#xff0c;遇到实际问题的&#xff0c;不要在这儿浪费时间。切记切记 软考之数据库一、概念数据模型&#xff08;下午题常考&#xff09;二、结构数据模型关系模型1、关系模型中基本术语2、关系模型中的关系完整性约束3、关系代数…

Flutter-Scaffold组件

在Flutter开发当中&#xff0c;我们可能会遇到以下的需求&#xff1a;实现页面组合使用&#xff0c;比如说有悬浮按钮、顶部菜单栏、左右抽屉侧边栏、底部导航栏等等效果。Scaffold组件可以帮我们实现上面需求说的效果。这篇博客主要分享容器组件的Scaffold组件的使用&#xff…

前后台协议联调拦截器

前后台协议联调&拦截器4&#xff0c;前后台协议联调4.1 环境准备4.2 列表功能4.3 添加功能4.4 添加功能状态处理4.5 修改功能4.6 删除功能5&#xff0c;拦截器5.1 拦截器概念5.2 拦截器入门案例5.2.1 环境准备5.2.2 拦截器开发步骤1:创建拦截器类步骤2:配置拦截器类步骤3:S…

快速玩转 CNStack 2.0 流量防护

作者&#xff1a;冠钰 云原生下的服务治理 在云原生技术的演进过程中&#xff0c;依托云原生技术能力&#xff0c;形成一个可以向下管理基础设施&#xff0c;向上管理业务应用的技术中台&#xff0c;越来越成为企业期望的云原生技术落地趋势。随着云原生技术中台 CNStack 发布…

逍遥自在学C语言 | 逻辑运算符

前言 一、人物简介 第一位闪亮登场&#xff0c;有请今后会一直教我们C语言的老师 —— 自在。 第二位上场的是和我们一起学习的小白程序猿 —— 逍遥。 二、构成和表示方式 逻辑运算符是用来比较和操作布尔值的运算符C语言中的逻辑运算符主要有3个&#xff0c;如下表所示 运…

vue echarts 画饼图

页面&#xff1a; {{--饼图--}}<template><div class"col-sm-6"><div id"mychart" :style"{width: 100%, height: 400px}"></div></div></template>pie_data: [], //饼图myChart: {},pieName: [],/** 再画…

论文阅读《LargeKernel3D: Scaling up Kernels in 3D Sparse CNNs》

论文地址&#xff1a;https://arxiv.org/pdf/2206.10555.pdf 源码地址&#xff1a;https://github.com/dvlab-research/LargeKernel3D 前言 3D 大核 CNN 设计难点主要分为两个方面&#xff1a; 模型计算效率: 增大3维卷积核时&#xff0c;参数量和计算负担的增长速度比 2D CN…

【Linux】理解Linux中硬链接和软链接

Linux中硬链接和软链接0 引言1 硬链接&#xff08;Hard Link&#xff09;1.1 让文件之间产生硬链接关系1.2 不能给目录创建硬链接2 软链接&#xff08;Sort Link&#xff09;2.1 让文件产生软链接关系2.2 目录也可以产生软链接关系2.3 软链接的应用场景3 总结0 引言 在之前的文…

蓝桥杯真题2021c++省A题解

[蓝桥杯 2021 省 A] 填空问题 试题 A&#xff1a;卡片 小蓝有很多数字卡片&#xff0c;每张卡片上都是数字 000 到 999 。 小蓝准备用这些卡片来拼一些数&#xff0c;他想从 111 开始拼出正整数&#xff0c;每拼一个&#xff0c;就保存起来&#xff0c;卡片就不能用来拼其它…

Vue3+vite2 博客前端开发

Vue3vite2 博客前端开发 文章目录Vue3vite2 博客前端开发前言页面展示代码设计卡片设计背景&#xff08;Particles.js粒子效果&#xff09;右侧个人信息与公告内容页友链总结前言 大家是否也想拥有一个属于自己的博客&#xff1f;但是如何去开发博客&#xff0c;怎样去开发一个…

【Verilog基础】二进制比较器

文章目录 一、二进制比较器1、1、一位数值比较器(是多位比较器的基础)1、2、两位数值比较器`A1A0`比`B1B0`1、3、典型数值比较器之:四位数值比较器`A3A2A1A0`比`B3B2B1B0`1、4、位数扩展数值比较器:串联、并联二、例题:四位数值比较器一、二进制比较器 1、1、一位数值比较…

一文讲清深力科工业与能源行业首选大电流 600V HVIC 高低边驱动产品SLM21814CJ-DG代替UCC27714DR 特性简述

一文讲清深力科工业与能源行业首选大电流 600V HVIC 高低边驱动产品SLM21814CJ-DG代替UCC27714DR 特性简述 SLM21814CJ-DG是一款大电流的 600V HVIC 高低边驱动产品&#xff0c;峰值拉电流为 2.5A&#xff0c;灌电流为 3.5A&#xff0c;同时可为两个通道提供 8.9V/8.2V 的欠压…

并发编程(十)-ScheduledThreadPoolExecutor源码分析

一、ScheduledThreadPoolExecutor 概述 ScheduledThreadPoolExecutor 是 Java 中的一个线程池实现&#xff0c;它继承自 ThreadPoolExecutor 类&#xff0c;并实现了 ScheduledExecutorService 接口&#xff0c;ScheduledThreadPoolExecutor内部维护了一个任务队列和一组线程&a…

代码随想录Day44

今天继续学习通过动态规划解决问题 96.不同的二叉搜索树 给你一个整数 n &#xff0c;求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种&#xff1f;返回满足题意的二叉搜索树的种数。 示例 1&#xff1a; 输入&#xff1a;n 3 输出&#xff1a;5 思路…
最新文章