优先级队列(大根堆与小根堆)

news2024/11/20 7:28:38

优先级队列(大根堆与小根堆)

文章目录

  • 优先级队列(大根堆与小根堆)
      • 堆的介绍
      • 模拟堆
        • 以数组模型为例,创建堆
        • 向下调整(shiftDown)
        • 入队(push)及向上调整(shiftUp)
        • 出堆及获取堆顶元素

堆的介绍

优先级队列(PriorityQueue)其实就是所谓的堆,堆是一颗完全二叉树下的一种形态。存储数据在堆中为何是完全二叉树呢?是这样的,使用完全二叉树时可以避免空间的浪费,这也是堆的存储模式特别之处,如果是一些不连续的数组,采用顺序表存储更好。

堆的使用:

在这里插入图片描述

这是最简单的创建一个堆,我们可以看见,堆的特别之处是可以用于排序,所以对于排序的几种方法中,就有堆排序这种方案,Java中提供的默认堆是大根堆。

堆分为两种,大根堆和小根堆,根据名称可知大根堆就是最大的数字就是根节点,且满足每颗子树都是大根堆,此时该树就是大根堆,小根堆也是如此。

如图:

在这里插入图片描述

需要每颗子树都满足大根堆/小根堆的条件才算做堆。

模拟堆

接下来使用代码来建造一个堆,首先我们要知道堆有哪些功能,可以做那些事情,堆的基本功能如下,堆在加入元素时会自动排列好,使得堆依旧有序。

public class Test {
    public void use() {
        PriorityQueue<Integer> queue = new PriorityQueue<>();
         queue.add(0);//添加元素到堆中
         queue.offer(0);//添加元素到堆中
        queue.isEmpty();//判断堆中是否还有元素
        queue.size();//计算堆中还有多少元素
        queue.peek();//查看堆首元素
        queue.poll();//弹出堆首元素
    }
}

在源码中,堆会自动扩容,所以接下来我们需要模拟实现一个堆也需要添加这项功能。

以数组模型为例,创建堆

创建一个初始化堆:

public class PriorityQueue {
    //创建一个全局变量用于排序(存储)
    public int[] elem;
    //记录使用空间的大小
    public int usedSize;
    //初始大小设置为10
	public PriorityQueue() {
        this.elem = new int[10];
    }
    //扩容方法
    private void superSet(){
        //直接将数组扩大两倍
        elem = Arrays.copyOf(elem,elem.length*2);
    }
}

上面使用了扩容,那接下来就需要判断数组满否和使用空间的大小:

public class PriorityQueue {
    //判断空间是否满了
	public boolean isFull() {
        return usedSize == elem.length;
    }
    //返回堆中元素个数
    public int size(){
        return useSize;
    }
}

接下来就开始建堆:

public class PriorityQueue {
	//建堆方法
	public int[] createHeap(int[] array) {
        for (int i = 0; i < array.length; i++) {
            //判断数组满否
            if(isFull()){
                //扩容
                superSet();
            }
            elem[i]=array[i];
            usedSize++;
        }
        //从最低最右的子树开始建堆
        for (int parent = (usedSize-2)/2; parent >=0 ; parent--) {
            //调用向下建堆方法
            shiftDown(parent,usedSize);
        }
        //将建好的数组返回
        int[] ret = new int[usedSize];
        for (int i = 0; i < usedSize; i++) {
            ret[i] = elem[i];
        }
        return ret;
    }
    
}

向下调整(shiftDown)

在这里插入图片描述

//向下建堆
public class PriorityQueue {
    
    //将父节点和边界值传入,len是代表最后元素的下标
    private void shiftDown(int parent,int len){
        //得到孩子下标,因为需要和孩子下标对比
        int child = 2*parent+1;
        //循环条件:至少有一个左孩子
        while(child<len){
            //判断是否存在右孩子,只需要得到值最大的孩子即可
            if(child+1<len && elem[child]<elem[child+1]){
                //如果右孩子的值大于左孩子,将下标移动到右孩子
                child++;
            }
            if(elem[parent] < elem[child]){
                //如果父节点小于子节点的值,进行交换
                int temp =elem[child];
                elem[child]=elem[parent];
                elem[parent]=temp;
                //判断下一棵子树是否为大根堆
                parent = child;
                child = parent*2+1;
            }else{
                //父节点大于子节点,结束此次循环
                break;
            }
        }
    }
    
}

向下建堆,需要注意不能越界和对父节点与子节点的比较,如果交换好,也需要判断接下来的子树是否满足条件。

入队(push)及向上调整(shiftUp)

在入堆之前,我们不妨思考一下!入堆是从入好还是从入好。

在这里插入图片描述

按照方法一头插相当于向下调整,在后面还需要扩大一个空间来存储加入的数字方法二更容易的将数字向上调整,也不怕越界,遇到需要跳针的可以直接进行交换,这便是向上调整

//向上调整
public class PriorityQueue {
    //向上调整主要是针对孩子节点向上交换的过程
	private void shiftUp(int child){
        //得到父节点
        int patent = (child-1)/2;
        //判断此时是否child是否为0,为0则是最后一个节点
        while(child > 0){
            if(elem[parent] < elem[child]){
                int tmp =elem[child];
                elem[child] = elem[parent];
                elem[parent] =tmp;
                //继续向上
                child = parent;
                parent = (child-1)/2;
            }else {
            	//子节点值小于父节点,直接结束
                break;
            }
        }
    }
    
}

出堆及获取堆顶元素

//弹出堆顶元素
public int pollHeap() {
    //保存堆顶元素
	int tmp = elem[0];
    //将堆顶元素变成最后一个元素
    elem[0] = elem[usedSize];
    usedSize--;
    //向下调整  
    shiftDown(0,usedSize);
    //返回堆顶元素
    return tmp;   
}
//判断是否为空
public boolean isEmpty() {
        return usedSize == 0;
    }
//弹出堆顶元素
public int peekHeap() {
        return elem[0];
    }

以上就是模拟堆的实现,接下来就来实验一下:

int[] array = {23,32,83,92,43,24,53};

输出:

在这里插入图片描述

添加:72

在这里插入图片描述

在这里插入图片描述

以上就是关于优先级队列的全部内容,关于建堆,与一些实现方法,欢迎交流🙋。

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

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

相关文章

java获取文件夹下所有文件名

在进行 Java编程的过程中&#xff0c;我们会经常使用到文件夹下的所有文件名。有时候可能不太熟悉 Java编程的小伙伴们会发现&#xff0c;在代码中没有获取到所有的文件名&#xff0c;那么这个时候我们应该怎么去获取到这些文件呢&#xff1f;在进行 Java编程的过程中&#xff…

《花雕学AI》31:ChatGPT--用关键词/咒语/提示词Prompt激发AI绘画的无限创意!

你有没有想过用AI来画画&#xff1f;ChatGPT是一款基于GPT-3的聊天模式的AI绘画工具&#xff0c;它可以根据你输入的关键词/咒语/提示词Prompt来生成不同风格和主题的画作。Prompt是一些简短的文字&#xff0c;可以用来指导ChatGPT的创作过程。在这篇文章中&#xff0c;我将展示…

2个月快速通过PMP证书的经验分享

01 PMP证书是什么&#xff1f; 指的是项目管理专业人士资格认证。它是由美国项目管理协会&#xff08;Project Management Institute(简称PMI)&#xff09;发起的&#xff0c;严格评估项目管理人员知识技能是否具有高品质的资格认证考试。其目的是为了给项目管理人员提供统一的…

Redis【性能 02】Redis-5.0.14伪集群和Docker集群搭建及延迟和性能测试(均无法提升性能)

伪集群及Docker集群搭建测试流程 1.伪集群搭建1.1 环境1.2 搭建1.2.1 集群配置1.2.2 生成其他5个节点配置1.2.3 启动并验证节点状态1.2.4 创建集群1.2.5 集群信息 1.3 测试 2.Docker集群2.1 环境2.2 搭建2.2.1 创建专用网络2.2.2 生成配置文件2.2.3 容器启动及验证2.2.4 创建集…

NIST SP 800-193: BIOS 平台固件弹性指南

NIST SP 800-147&#xff0c;BIOS 保护指南 ( NIST SP 800-147 [1]、NIST SP 800-147B [2]&#xff09;解决了 BIOS 的保护问题 可从此处免费获得&#xff1a; https://doi.org/10.6028/NIST.SP.800-193 摘要 此文档提供了关于支持平台固件和数据对抗潜在地具有破坏性的攻…

python的 __init__.py文件中使用__all__变量

在Python的包&#xff08;Package&#xff09;中&#xff0c;init.py文件可以被用作初始化包的脚本。这个文件会在包被导入时自动执行。同时&#xff0c;init.py文件中的__all__变量也可以被用来限制包中可导入的模块、类或方法。具体来说&#xff0c;__all__变量应该是一个列表…

项目上线 | 兰精携手盖雅工场,数智驱动绿色转型

近年来&#xff0c;纺织纤维行业零碳行动如火如荼。作为低碳环保消费新时尚引领者&#xff0c;同时也是纤维领域隐形冠军&#xff0c;兰精在推进绿色发展的同时&#xff0c;也在不断向内探索企业数字化转型之道&#xff0c;以此反哺业务快速扩张。 数智转型&#xff0c;管理先…

计算机网络面试题(上)

1.TCP/IP 网络模型有哪几层&#xff1f; TCP/IP 网络通常是由上到下分成 4 层&#xff0c;分别是应用层&#xff0c;传输层&#xff0c;网络层和网络接口层。 每一层的封装格式&#xff1a; 网络接口层的传输单位是帧&#xff08;frame&#xff09;&#xff0c;IP 层的传输单位…

探究肺癌患者的CT图像的图像特征并构建一个诊断模型

目标效果图操作说明代码 目标 探究肺癌患者的CT图像的图像特征并构建一个诊断模型 效果图 操作说明 代码中我以建立10张图为例&#xff0c;多少你自己定 准备工作&#xff1a; 1.准备肺癌或非肺癌每个各10张图&#xff0c;在本地创建一个名为“data”的文件夹&#xff0c;用…

【Docker】什么是Dockerfile

文章目录 1、认识DockerFile2、DockerFile的构建过程3、DockerFile常用指令4、实战&#xff1a;构建自己的centos5、CMD和ENTRYPOINT的区别6、DockerFile制作tomcat镜像7、发布镜像到DockerHub8、发布镜像到阿里云 1、认识DockerFile Dockerfile是用来构建docker镜像的文件&am…

arduino stm32 开发环境 解决方案

用到工具 hfs.exe 做文件服务器 来模拟所有需要下载的文件 https://download.csdn.net/download/qq_32562225/87754346 其原理就相当于 本应arduinoIDE 下载的文件&#xff0c;先手动通过迅雷工具下载下来&#xff0c;然后再添加到文件服务器中&#xff0c;这样就可以快速…

爬虫想要的HTML

我的个人博客主页&#xff1a;如果’真能转义1️⃣说1️⃣的博客主页 关于Python基本语法学习---->可以参考我的这篇博客&#xff1a;《我在VScode学Python》 接下来回更新一个关于urllib的文章 爬虫一个新浪博客地址 import urllib.requestpage 1 url [" "] *…

如何在线录制视频?教您一个简单的方法!

案例&#xff1a;怎样实现在线录屏&#xff1f; 【听朋友说在线录屏更加便捷&#xff0c;我也想学习如何在线录制电脑屏幕。有没有小伙伴有在线录屏的经验&#xff0c;求好心人给一个简单的方法&#xff01;】 在今天的数字时代&#xff0c;我们经常需要录制电脑屏幕来制作教…

【C++】AVL树的插入实现(详解旋转机制)

✍作者&#xff1a;阿润菜菜 &#x1f4d6;专栏&#xff1a;C 文章目录 AVL树的定义AVL树的旋转机制1.左旋操作 --- 新节点插入较高右子树的右侧---右右&#xff1a;左单旋2.右旋操作 --- 新节点插入较高左子树的左侧——左左&#xff1a;右单旋3.左右双旋 --- 新节点插入较高左…

JMeter开发自动化接口测试脚本练习

一、打开浏览器代理服务器设置 我这里用的是360浏览器&#xff0c;打开浏览器代理服务器设置&#xff0c;端口要与jmeter中的端口设置保持一致哦。 二、JMeter设置代理 JMeter设置代理&#xff08;jmeter中的端口要与360浏览器端口设置保持一致哦。&#xff09; 三、启动代理运…

BM6 判断链表中是否有环

判断链表中是否有环_牛客题霸_牛客网 (nowcoder.com) 双指针&#xff0c;快指针一次走两步&#xff0c;慢指针一次走一步&#xff0c;快指针不为空且快指针的下一个指针不为空的情况下 若快慢指针相遇即位有环。 /** * Definition for singly-linked list. * struct ListNode {…

基于RK3588的8K智能摄像机方案设计

设计了一款基于石墨烯散热的8 K智能摄像头&#xff0c;主控采用瑞芯微RK3588&#xff0c;传感器采用索尼IMX435&#xff0c; 通过HDMI2.1将传感器采集到的图像发送到8 K显示器&#xff0c;实现端到端的8 K呈现&#xff0c;为了确保摄像头性能稳定&#xff0c;本 设计采用石墨烯…

ETL到底是什么?

各位数据的朋友&#xff0c;大家好&#xff0c;我是老周道数据&#xff0c;和你一起&#xff0c;用常人思维数据分析&#xff0c;通过数据讲故事。 前段时间和大家聊了一个话题&#xff0c;就是为什么要用构建数据仓库&#xff0c;而不是直连数据源的方式开发报表&#xff1f;通…

七、MyBatis自定义映射resultMap

文章目录 七、自定义映射resultMap7.1 resultMap处理字段和属性的映射关系7.2 多对一映射处理级联方式处理映射关系使用association处理映射关系分步查询 7.3 一对多映射处理collection分步查询 本人其他相关文章链接 七、自定义映射resultMap 注意&#xff1a;下面两行表看看…

公司新来的00后真是卷王,工作没2年,跳槽到我们公司起薪18K都快接近我了

说00后躺平了&#xff0c;但是有一说一&#xff0c;该卷的还是卷。这不&#xff0c;前段时间我们公司来了个00后&#xff0c;工作都没两年&#xff0c;跳槽到我们公司起薪18K&#xff0c;都快接近我了。后来才知道人家是个卷王&#xff0c;从早干到晚就差搬张床到工位睡觉了。 …