Java实现优先级队列(堆)

news2024/12/23 18:46:07

前言

在学习完二叉树的相关知识后,我们对数据结构有了更多的认识,本文将介绍到优先级队列(堆)

1.优先级队列

1.1概念

前面介绍过队列,队列是一种先进先出(FIFO)的数据结构,但有些情况下,操作的数据可能带有优先级,一般出队列时,可能需要优先级高的元素先出队列,该中场景下,使用队列显然不合适,对此数据结构应该提供两个最基本的操作,一个是返回最高优先级对象一个是添加新的对象。这种数据结构就是优先级队列(Priority Queue)

1.2模拟实现

JDK1.8中的PriorityQueue底层使用了堆这种数据结构,而堆实际就是在完全二叉树的基础上进行了一些调整

2.堆

2.1概念

如果有一个关键码的集合K = {k0,k1, k2,…,kn-1},把它的所有元素按完全二叉树的顺序存储方式存储在一个一维数组中,并满足:Ki <= K2i+1 且 Ki<= K2i+2 (Ki >= K2i+1 且 Ki >= K2i+2) i = 0,1,2…,则称为小堆(或大堆)。将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆 


2.2性质 

1.堆中某个节点的值总是不大于或不小于其父节点的值
2.堆总是一棵完全二叉树

2.3堆的存储方式

根据堆的概念以及性质,我们可以根据层序的规则采用顺序的方式来高效存储

注意:对于非完全二叉树,则不适合使用顺序方式进行存储,因为为了能够还原二叉树,空间中必须要存储空节点,就会导致空间利用率比较低

根据我们对二叉树性质的学习,有一下性质:

如果i为0,则i表示的节点为根节点,否则i节点的双亲节点为 (i - 1)/2
如果2 * i + 1 小于节点个数,则节点i的左孩子下标为2 * i + 1,否则没有左孩子
如果2 * i + 2 小于节点个数,则节点i的右孩子下标为2 * i + 2,否则没有右孩子

2.4堆的创建 

我们以集合{ 27,15,19,18,28,34,65,49,25,37 }中的数据为例,建堆

按照二叉树的顺序排列发现,根子树已经为堆的结构,只需将根节点向下调整即可

2.4.1向下调整

以大根堆为例

    private void swap(int i,int j){
        int tmp=elem[i];
        elem[i]=elem[j];
        elem[j]=tmp;
    }
    //大根堆
    /*
    时间复杂度为从根一路比较到叶子,比较的次数为完全二叉树的高度,O(log2 n)
     */
    public void siftDown(int parent,int end){
        int child=parent*2+1;//先标记左孩子,因为可能该树没有右孩子
        while(child<end) {
            if (child + 1 < end && elem[child] < elem[child + 1]) {//假如右孩子存在,找到其中较大的孩子
                child++;
            }
            //找到了最大的子孩子
            if (elem[child] > elem[parent]) {//若孩子比双亲大,进行交换,同时继续向下调整
                swap(child, parent);
                parent = child;
                child = 2 * parent + 1;
            } else {//若双亲大,则满足堆的特性,即跳出循环
                break;
            }
        }
    }

注意:在调整以parent为根的二叉树时,必须要满足parent的左子树和右子树已经是堆了才可以向下调整

2.4.2堆创建

但是当二叉树中,子树不满足堆时,该如何建堆呢?

这里,我们找到第一个非叶子节点,从该节点开始往前一直到根节点,遇到一个节点,向下调整

    public void creatHeap(){
        for (int parent = (usedSize-1-1/2); parent >=0 ; parent--) {
            siftDown(parent,usedSize);
        }
    }

2.5堆的插入与删除 

 2.5.1插入

堆的插入总共需要两个步骤:
1. 先将元素放入到底层空间中(注意:空间不够时需要扩容)
2. 将最后新插入的节点向上调整,直到满足堆的性质

//以大根堆为例
    public void siftUp(int child){
        int parent=(child-1)/2;
        while(parent>=0){
            if(elem[child]>elem[parent]){
                swap(child,parent);
                child=parent;
                parent=(child-1)/2;
            }else{
                break;
            }
        }
    }

2.5.2删除

注意:堆的删除一定删除的是堆顶元素
1. 将堆顶元素对堆中最后一个元素交换
2. 将堆中有效数据个数减少一个
3. 对堆顶元素进行向下调整
 

  public boolean isFull(){
        return usedSize==elem.length;
    }

    public int poll(){
        if(isEmpty()){
            return -1;
        }
        int old=elem[0];
        swap(0,usedSize-1);
        usedSize--;
        siftDown(0,usedSize-1);
        return old;
    }
  public boolean isEmpty(){
        return usedSize==0;
    }

2.6模拟实现优先级

public class Test {
    public static void main(String[] args) {
        int[] array = {25, 56, 21, 45, 75};
        TestHeap testHeap = new TestHeap();
        testHeap.init(array);
        testHeap.creatHeap();

        testHeap.heapSort();

    }
}

 如果上述内容对您有帮助,希望给个三连谢谢!

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

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

相关文章

【机器学习】探究Q-Learning通过学习最优策略来解决AI序列决策问题

꒰˃͈꒵˂͈꒱ write in front ꒰˃͈꒵˂͈꒱ ʕ̯•͡˔•̯᷅ʔ大家好&#xff0c;我是xiaoxie.希望你看完之后,有不足之处请多多谅解&#xff0c;让我们一起共同进步૮₍❀ᴗ͈ . ᴗ͈ აxiaoxieʕ̯•͡˔•̯᷅ʔ—CSDN博客 本文由xiaoxieʕ̯•͡˔•̯᷅ʔ 原创 CSDN …

学会 Python 后可以做什么副业?

近年来&#xff0c;Python凭借其简洁易入门的特点受到越来越多人群的青睐。 当然这不仅仅是针对程序员来说&#xff0c;对于一些学生、职场人士也是如此。 Python为什么会大受欢迎呢&#xff1f;因为Python还被大家称为“胶水语言&#xff0c;它适用于网站、桌面应用开发、[自…

蓝牙耳机哪个牌子好用?力荐五款实力超群机型,快收藏!

​随着蓝牙耳机的普及&#xff0c;越来越多的年轻人开始追求这种无线的便利。市场上品牌众多&#xff0c;款式多样&#xff0c;选择起来确实让人眼花缭乱。我整理了一份蓝牙耳机品牌排行榜前十名&#xff0c;希望能为你提供一些参考&#xff0c;帮助你找到心仪的耳机。 一、如何…

C语言堆区内存管理

一、C语言编译的内存分配 二、堆区空间的分配 1、malloc函数 功能&#xff1a;从堆区分配内存 #include <stdlib.h> void *malloc(unsigned int size)//size 分配内存的字节数2、free函数 功能&#xff1a;释放内存 #include <stdlib.h> void free(void *ptr)…

L2-045 堆宝塔 - java

L2-045 堆宝塔 Java (javac) 时间限制 500 ms 内存限制 256 MB 其他编译器 时间限制 400 ms 内存限制 64 MB 栈限制 8192 KB 题目描述&#xff1a; 堆宝塔游戏是让小朋友根据抓到的彩虹圈的直径大小&#xff0c;按照从大到小的顺序堆起宝塔。但彩虹圈不一定是按照直径的大小顺…

Java NIO,高效操作I/O流的必备技能

Java IO在工作中其实不常用到&#xff0c;更别提NIO了。但NIO却是高效操作I/O流的必备技能&#xff0c;如顶级开源项目Kafka、Netty、RocketMQ等都采用了NIO技术&#xff0c;NIO也是大多数面试官必考的体系知识。虽然骨头有点难啃&#xff0c;但还是要慢慢消耗知识、学以致用哈…

Spring核心容器总结

2.2 核心容器总结 2.2.1 容器相关 BeanFactory是IoC容器的顶层接口&#xff0c;初始化BeanFactory对象时&#xff0c;加载的bean延迟加载 ApplicationContext接口是Spring容器的核心接口&#xff0c;初始化时bean立即加载 ApplicationContext接口提供基础的bean操作相关方法…

CTFHUB-技能树-Web前置技能-文件上传(无验证,JS前端验证,前端验证)

CTFHUB-技能树-Web前置技能-文件上传&#xff08;无验证&#xff0c;JS前端验证&#xff0c;前端验证—.htaccess&#xff09; 文章目录 CTFHUB-技能树-Web前置技能-文件上传&#xff08;无验证&#xff0c;JS前端验证&#xff0c;前端验证—.htaccess&#xff09;文件上传无验…

基于 LSTM 模型的古诗词自动生成算法实现及系统实现

近年来&#xff0c;研究者在利用循环神经网络&#xff08;Recurrent Neural Network&#xff0c;RNN&#xff09;进行古诗自动生成方面取得了显著的效果。但 RNN 存在梯度问题&#xff0c;导致处理时间跨度较长的序列时 RNN 并不具备长期记忆存储功能。随后&#xff0c;出现的基…

(十一)C++自制植物大战僵尸游戏客户端更新实现

植物大战僵尸游戏开发教程专栏地址http://t.csdnimg.cn/cFP3z 更新检查 游戏启动后会下载服务器中的版本号然后与本地版本号进行对比&#xff0c;如果本地版本号小于服务器版本号就会弹出更新提示。让用户选择是否更新客户端。 在弹出的更新对话框中有显示最新版本更新的内容…

全球化背景下的海外社媒营销战略:趋势洞察与策略调整

随着全球化的不断深入&#xff0c;企业在海外市场的竞争愈发激烈。在这一背景下&#xff0c;海外社交媒体平台成为了企业品牌推广和营销的重要渠道。本文Nox聚星将和大家探讨全球化背景下&#xff0c;企业如何利用海外社交媒体平台进行品牌推广和营销&#xff0c;并分析企业如何…

Git分布式版本控制系统——在IDEA中使用Git(一)

一、在IDEA中配置Git 本质上还是使用的本地安装的Git软件&#xff0c;所以需要在IDEA中配置Git 打开IDEA的设置页面&#xff0c;按照下图操作 二、在IDEA中使用Git获取仓库 1、本地初始化仓库 2、从远程仓库克隆 方法一&#xff1a; 方法二&#xff1a; 三、.gitignore文件…

#陶晶驰串口屏使用

1.陶晶驰串口屏输入要连接的wifi信息实现 &#xff08;1&#xff09;选择文本控件 &#xff08;2&#xff09;给文本控件配置输入键盘&#xff0c;id代表用户名&#xff0c;password代表wifi密码&#xff08;注意wifi的频段需要为2.4GHz&#xff09; &#xff08;3&#xff0…

k8s之etcd

1.特点&#xff1a; etcd 是云原生架构中重要的基础组件。有如下特点&#xff1a; 简单&#xff1a;安装配置简单&#xff0c;而且提供了 HTTP API 进行交互&#xff0c;使用也很简单键值对存储&#xff1a;将数据存储在分层组织的目录中&#xff0c;如同在标准文件系统中监…

RAG (Retrieval Augmented Generation) 结合 LlamaIndex、Elasticsearch 和 Mistral

作者&#xff1a;Srikanth Manvi 在这篇文章中&#xff0c;我们将讨论如何使用 RAG 技术&#xff08;检索增强生成&#xff09;和 Elasticsearch 作为向量数据库来实现问答体验。我们将使用 LlamaIndex 和本地运行的 Mistral LLM。 在开始之前&#xff0c;我们将先了解一些术…

性能工具之emqtt-bench BenchMark 测试示例

文章目录 一、前言二、典型压测场景三、机器准备四、典型压测场景1、并发连接2、消息吞吐量测试2.1 1 对 1&#xff08;示例&#xff09;2.2 多对1&#xff08;示例&#xff09;2.3 1对多&#xff08;示例&#xff09; 五、遇到的问题client(): EXIT for {shutdown,eaddrnotava…

OpenStack镜像管理与制作

一、OpenStack镜像服务 1、什么是镜像 镜像通常是指一系列文件或一个磁盘驱动器的精确副本。虚拟机所使用的虚拟磁盘&#xff0c;实际上是一种特殊格式的镜像文件。云环境下尤其需要镜像。镜像就是一个模板&#xff0c;类似于VMware的虚拟机模板&#xff0c;其预先安装基本的…

五步教你正确申请免费SSL证书

在当今数字化时代&#xff0c;保护网站数据安全和提升用户信任至关重要&#xff0c;而实现这一目标的有效途径之一便是为网站部署SSL&#xff08;Secure Sockets Layer&#xff09;证书。SSL证书能够加密网站与用户之间的通信&#xff0c;确保敏感信息不被第三方窃取。幸运的是…

1.8.5 卷积神经网络近年来在结构设计上的主要发展和变迁——Inception-v4 和 Inception-ResNet

1.8.5 卷积神经网络近年来在结构设计上的主要发展和变迁——Inception-v4 和 Inception-ResNet 前情回顾&#xff1a; 1.8.1 卷积神经网络近年来在结构设计上的主要发展和变迁——AlexNet 1.8.2 卷积神经网络近年来在结构设计上的主要发展和变迁——VGGNet 1.8.3 卷积神经网络近…

一篇安装配置ubuntu22.04(步骤详细,配置成功)

一篇配置ubuntu22.04(步骤详细&#xff0c;配置成功) 官网下载相应的镜像 vitualbox安装ubuntu 新建虚拟机 第一步 第二步 第三步、按需分配内存、处理器个数、磁盘大小 第四步、一直下一步直至完成 配置虚拟机网络 第一步、先停止虚拟机 第二步、设置虚拟机网络 正常启…