Java数据结构——优先队列

news2025/1/22 17:44:31

目录

  • 引言
  • 1. 优先队列
  • 2. 优先队列的实现
    • 2.1 堆的概念
    • 2.2 堆的创建
    • 2.2.1 堆的向下调整
    • 2.3 堆的插入
    • 2.4 堆的删除
  • 3. 总结

引言

前面一篇文章讲了二叉树,本篇将讲述数据结构中的优先队列,优先队列则需要用到完全二叉树来实现。

1. 优先队列

队列(Queue)是一个线性数据结构,它的理念是“先进先出”,而优先队列(Priority Queue)是一种特殊的队列数据结构,其中每个元素都有一个优先级,元素按照优先级进行排序。也就是说,要保证每次都是优先级最高的元素进行出列。

2. 优先队列的实现

既然队列是线性数据结构,为何还需要用二叉树?
优先队列本身确实是线性结构,但是优先队列的核心需求是高效地插入元素和删除具有最高优先级的元素。为了满足这一要求,需要用到堆这一数据结构。下面将对堆来进行介绍,并使用堆来完成优先队列的相关操作。

2.1 堆的概念

堆(Heap)是一种特殊的完全二叉树数据结构,分为大顶堆(也叫大根堆)(Max Heap)和小顶堆(小根堆)(Min Heap)。堆是一棵完全二叉树,以数组方式存储,且数组中的元素 Ki 满足 Ki <= K2i+1 且Ki <= K2i+2,这则是小顶堆,若是>= 则是大顶堆。
堆的存储:
{1,2,3,4,5,6,7,8,9,10}
在这里插入图片描述

2.2 堆的创建

以如下集合来创建堆:{65,50,23,81,75,32,16,7,43,3}
在这里插入图片描述

2.2.1 堆的向下调整

下面将以上面的乱序集合来建立堆。假设要构建大顶堆。不妨先将其中一个节点(23)进行调整,
用parent标记需要调整的节点,用child标记其左孩子。
在这里插入图片描述
然后判断child是否存在(即child小于usedSize)
存在则比较左孩子和右孩子的大小,将child下标改为值更大的下标。
而后比较child和parent对应的值大小,若child>parent,则交换,否则结束。
如此反复循环,直到child>=usedSize或者child<=parent。
代码如下:

private void siftDown(int parent, int usedSize) {
        int child = 2 * parent + 1;
        while(child < usedSize){
            if(child + 1 < usedSize && elem[child] < elem[child + 1]){
                child++;
            }
            if(elem[child] > elem[parent]){
                swap(child, parent);
                parent = child;
                child = 2 * parent + 1;
            }else{
                break;
            }
        }
    }

在这里插入图片描述
如果要全部调整,则需要从最后一个非叶子进行遍历,往前进行向下调整:

	public void createHeap(int[] array) {
        for(int parent = (array.length - 1 - 1) / 2; parent >= 0; parent--){
            siftDown(parent, array.length);
        }
    }

具体步骤如下:
步骤 1:调整节点索引 4(值为 75)
左子节点索引为 24 + 1 = 9,值为 3
右子节点索引为 2
4 + 2 = 10,不存在
节点 75 大于其左子节点 3,不需要调整。

步骤 2:调整节点索引 3(值为 81)
左子节点索引为 23 + 1 = 7,值为 7
右子节点索引为 2
3 + 2 = 8,值为 43
节点 81 大于其子节点 7 和 43,不需要调整。

步骤 3:调整节点索引 2(值为 23)
左子节点索引为 22 + 1 = 5,值为 32
右子节点索引为 2
2 + 2 = 6,值为 16
比较节点 23 和其左子节点 32,交换它们的位置:

	索引:  0   1   2   3   4   5   6   7   8   9
	数组: [65, 50, 32, 81, 75, 23, 16, 7, 43, 3]

在这里插入图片描述

继续调整节点 23 的位置:

左子节点索引为 25 + 1 = 11,不存在
右子节点索引为 2
5 + 2 = 12,不存在
节点 23 没有子节点,不需要进一步调整。

步骤 4:调整节点索引 1(值为 50)
左子节点索引为 21 + 1 = 3,值为 81
右子节点索引为 2
1 + 2 = 4,值为 75
比较节点 50 和其左子节点 81,交换它们的位置:

	索引:  0   1   2   3   4   5   6   7   8   9
	数组: [65, 81, 32, 50, 75, 23, 16, 7, 43, 3]

在这里插入图片描述

继续调整节点 50 的位置:

左子节点索引为 23 + 1 = 7,值为 7
右子节点索引为 2
3 + 2 = 8,值为 43
节点 50 大于其子节点 7 和 43,不需要进一步调整。

步骤 5:调整节点索引 0(值为 65)
左子节点索引为 20 + 1 = 1,值为 81
右子节点索引为 2
0 + 2 = 2,值为 32
比较节点 65 和其左子节点 81,交换它们的位置:

	索引:  0   1   2   3   4   5   6   7   8   9
	数组: [81, 65, 32, 50, 75, 23, 16, 7, 43, 3]

在这里插入图片描述

继续调整节点 65 的位置:

左子节点索引为 21 + 1 = 3,值为 50
右子节点索引为 2
1 + 2 = 4,值为 75
比较节点 65 和其右子节点 75,交换它们的位置:

	索引:  0   1   2   3   4   5   6   7   8   9
	数组: [81, 75, 32, 50, 65, 23, 16, 7, 43, 3]

在这里插入图片描述
继续调整节点 65 的位置:

左子节点索引为 24 + 1 = 9,值为 3
右子节点索引为 2
4 + 2 = 10,不存在
节点 65 大于其左子节点 3,不需要进一步调整。

	最后调整后的数组如下:{81 75 32 50 65 23 16 7 43 3}

在这里插入图片描述

2.3 堆的插入

插入操作如下:
先将新元素插入到最后一个位置,而后向上调整这个元素。
向上调整和向下调整反过来,将子节点与其父节点进行比较而后调整。

    private void siftDown(int parent, int usedSize) {
        int child = 2 * parent + 1;
        while(child < usedSize){
            if(child + 1 < usedSize && elem[child] < elem[child + 1]){
                child++;
            }
            if(elem[child] > elem[parent]){
                swap(child, parent);
                parent = child;
                child = 2 * parent + 1;
            }else{
                break;
            }
        }
    }

插入操作:

    public void offer(int val){
        if(isFull()){
            elem = Arrays.copyOf(elem, elem.length * 2);
        }
        elem[usedSize] = val;
        siftUp(usedSize);
        usedSize++;
    }

假设插入一个值为80的元素,操作如下:
在这里插入图片描述
在这里插入图片描述

2.4 堆的删除

堆的每次删除是指定位置,即删除根节点的元素。
操作如下:
交换根节点和最后一个节点的位置,usedSize减少1,而后对堆顶元素进行向下调整。 代码如下:

    public int poll(){
        if(isEmpty()){
            throw new UnsupportedOperationException("队列为空");
        }
        int ret = elem[0];
        elem[0] = elem[--usedSize];
        siftDown(0, usedSize);
        return ret;
    }

执行删除操作后:
在这里插入图片描述

3. 总结

到这就是优先队列的基本内容了,此外,使用优先队列可以对数据进行堆排序,将在后面讲述。

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

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

相关文章

51c大模型~合集105

我自己的原文哦~ https://blog.51cto.com/whaosoft/13101924 #刚刚&#xff0c;ChatGPT开始有了执行力&#xff01; 现在 AI 智能体可以 24*7 小时为你打工。 2025 刚过去了半个月&#xff0c;OpenAI 在智能体领域「开大」了。 今天&#xff0c;OpenAI 正在为 ChatGPT 推出…

从零到上线:Node.js 项目的完整部署流程(包含 Docker 和 CICD)

从零到上线&#xff1a;Node.js 项目的完整部署流程&#xff08;包含 Docker 和 CI/CD&#xff09; 目录 项目初始化&#xff1a;构建一个简单的 Node.js 应用设置 Docker 环境&#xff1a;容器化你的应用配置 CI/CD&#xff1a;自动化构建与部署上线前的最后检查&#xff1a;…

《自动驾驶与机器人中的SLAM技术》ch4:基于预积分和图优化的 GINS

前言&#xff1a;预积分图优化的结构 1 预积分的图优化顶点 这里使用 《自动驾驶与机器人中的SLAM技术》ch4&#xff1a;预积分学 中提到的散装的形式来实现预积分的顶点部分&#xff0c;所以每个状态被分为位姿&#xff08;&#xff09;、速度、陀螺零偏、加计零偏四种顶点&am…

Ubuntu系统更改IP,保姆级教程

原理概述 本篇文章所用工具&#xff1a; Xshell&#xff1a;点击下载 VMware Workstation Pro&#xff1a;点击下载 密钥需要自行搜索所下载的VMware对应版本密钥。 IP 地址 IP 地址&#xff08;Internet Protocol Address&#xff09;是分配给每个连接到计算机网络的设备的…

【Linux】进程管理(一篇入门-进程:基本概念、PCB进程块、进程的创建、等待、终止、状态,exec函数族的使用)

本节主要内容&#xff1a;进程的一些基本概念&#xff0c;进程控制块PCB&#xff0c;以及如何在一个C程序里创建进程、终止进程、等待进程&#xff0c;包括孤儿进程、僵尸进程等特殊状态的进程&#xff0c;并涉及回收进程的概念。最终是exec函数族的函数使用方法及用途。 程序与…

RabbitMQ 在实际应用时要注意的问题

1. 幂等性保障 1.1 幂等性介绍 幂等性是数学和计算机科学中某些运算的性质,它们可以被多次应⽤,⽽不会改变初始应⽤的结果. 应⽤程序的幂等性介绍 在应⽤程序中,幂等性就是指对⼀个系统进⾏重复调⽤(相同参数),不论请求多少次,这些请求对系统的影响都是相同的效果. ⽐如数据库…

EXCEL+Python搞定数据处理(第一部分:Python入门-第1章:为什么要用Python为Excel编程)

参考资料&#xff1a; ExcelPython飞速搞定数据分析与处理&#xff0c;[瑞士] 费利克斯朱姆斯坦 著&#xff0c;中国工信出版社、人民邮电出版社出版(“Python for Excel, by Felix Zumstein (O’Reilly). Copyright 2021 Zoomer Analytics LLC, 978-1-492-08100-5”) 将不定…

MPLS VPN 部署与应用

一.简介 MPLS&#xff0c;称之为多协议标签交换&#xff0c;在九十年代中期被提出来&#xff0c;用于解决传统IP报文依赖查表转发而产生的瓶颈&#xff0c;现多用于VPN技术&#xff0c;MPLS报头封装在数据链路层之上&#xff0c;网络层之下。本文为结合了华为技术和新华三技术…

麒麟操作系统服务架构保姆级教程(十三)tomcat环境安装以及LNMT架构

如果你想拥有你从未拥有过的东西&#xff0c;那么你必须去做你从未做过的事情 之前咱们学习了LNMP架构&#xff0c;但是PHP对于技术来说确实是老掉牙了&#xff0c;PHP的市场占有量越来越少了&#xff0c;我认识一个10年的PHP开发工程师&#xff0c;十年工资从15k到今天的6k&am…

67,【7】buuctf web [HarekazeCTF2019]Avatar Uploader 2(未完成版)

进入靶场 和上一题一母同胞&#xff0c;先把上一题的答案拖进去看看 区别在于上一题这块直接显示了flag&#xff0c;这里并没有 看看源码 加载不出来&#xff0c;ctrlu <!-- 上传头像的提示信息&#xff0c;说明上传要求 --><p>Please upload a PNG image less th…

QD Laser携“Lantana”激光器参展SPIE光子学西部展2025,聚焦紧凑型设计

据悉&#xff0c;QD Laser公司将在2025年SPIE光子学西部展览会上展出其最新产品——世界最小一体化紧凑型可见光激光器“Lantana”。该展会将于1月28日至30日在旧金山的Moscone中心举行。 在展会期间&#xff0c;QD Laser公司将现场展示这款超小型、轻便设备—— “Lantana”。…

63,【3】buuctf web Upload-Labs-Linux 1

进入靶场 点击pass1 查看提示 既然是上传文件&#xff0c;先构造一句话木马&#xff0c;便于用蚁剑连接 <?php eval($_POST[123])?> 上传木马 文件后缀写为.php.jpg 右键复制图片地址 打开蚁剑连接 先点击测试连接&#xff0c;显示成功后&#xff0c;再点击添加即可 …

不重启JVM,替换掉已经加载的类

不重启JVM&#xff0c;替换掉已经加载的类 直接操作字节码 使用ASM框架直接操作class文件&#xff0c;在类中修改代码&#xff0c;然后retransform就可以了 下边是BTrace官方提供的一个简单例子&#xff1a; package com.sun.btrace.samples;import com.sun.btrace.annotati…

使用插件SlideVerify实现滑块验证

作者gitee地址&#xff1a;https://gitee.com/monoplasty/vue-monoplasty-slide-verify 使用步骤&#xff1a; 1、安装插件 npm install --save vue-monoplasty-slide-verify 2、在main.js中进行配置 import SlideVerify from vue-monoplasty-slide-verify; Vue.use(SlideV…

Kafka 和 MQ 的区别

1.概述 1.1.MQ简介 消息中间件&#xff0c;其实准确的叫法应该叫消息队列&#xff08;message queue&#xff09;&#xff0c;简称MQ。其本质上是个队列&#xff0c;有FIFO的性质&#xff0c;即first in first out&#xff0c;先入先出。 目前市场上主流的MQ有三款&#xff…

61,【1】BUUCTF WEB BUU XSS COURSE 11

进入靶场 左边是吐槽&#xff0c;右边是登录&#xff0c;先登录试试 admin 123456 admiin# 123456 admin"# 123456 不玩了&#xff0c;先去回顾下xss 回顾完就很尴尬了&#xff0c;我居然用SQL的知识去做xss的题 重来 吐槽这里有一个输入框&#xff0c;容易出现存储型…

CAN 网络介绍

背景 在T-Box 产品开发过程中&#xff0c;我们离不开CAN总线&#xff0c;因为CAN总线为我们提供了车身的相关数据&#xff0c;比如&#xff0c;车速、油耗、温度等。用于上报TSP平台&#xff0c;进行国标认证&#xff1b;也帮助我们进行车身控制&#xff0c;比如车门解锁/闭锁…

【C++】在线五子棋对战项目网页版

目录 1.Websocket 1.1.Websocket的简单认识 1.2.什么是轮询呢&#xff1f; 1.3.websocket协议切换过程 1.4.websocketpp库常用接口认识 1.5.websocketpp库搭建服务器流程 1.6.websocketpp库搭建服务器 2.mysqlclient库-接口认识 3.项目模块的划分&#xff1a; 4.项目…

《鸿蒙 HarmonyOS 应用开发从入门到精通(第 2 版)》学习笔记 ——HarmonyOS 环境搭建之安装DevEco Studio

作为一款开发工具&#xff0c;除了具有基本的代码开发、编译构建及调测等功能外&#xff0c;DevEco Studio还具有如下特点&#xff1a; 高效智能代码编辑&#xff1a;支持Java、XML、ArkTS、JS、C/C等语言的代码高亮、代码智能补齐、代码错误检查、代码自动跳转、代码格式化、…

2025年最新深度学习环境搭建:Win11+ cuDNN + CUDA + Pytorch +深度学习环境配置保姆级教程

本文目录 一、查看驱动版本1.1 查看显卡驱动1.2 显卡驱动和CUDA对应版本1.3 Pytorch和Python对应的版本1.4 Pytorch和CUDA对应的版本 二、安装CUDA三、安装cuDANN四、安装pytorch五、验证是否安装成功 一、查看驱动版本 1.1 查看显卡驱动 输入命令nvidia-smi可以查看对应的驱…