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

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

文章目录

  • 优先级队列(大根堆与小根堆)
      • 堆的介绍
      • 模拟堆
        • 以数组模型为例,创建堆
        • 向下调整(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

在这里插入图片描述

在这里插入图片描述

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

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

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

相关文章

SLAM中将地图映射到谷歌地图上的方法——完美运行

文章目录 前言一、rviz_satellite二、mapviz 前言 老是看到论文中有将地图映射到谷歌地图上的图&#xff0c;实在是泰裤辣&#xff01;&#xff01;&#xff08;武汉大学&#xff09; 搜索了很久&#xff0c;发现有两种可视化软件&#xff0c;分别为rviz_satellite和mapviz。…

第4章-动态规划

第4章-动态规划 总分&#xff1a;100分 得分&#xff1a;100.0分 10.0 分 1 . 多选题 中等 10分 有关0-1背包问题,用c[i][j]描述子问题:1...i共i个物品,背包容量为j的最优值(装入背包的最大价值),则其子问题为:1...i-1共i-1个物品,背包容量为j-w ix i,以下说法正确的是( AB…

如何利用分钟级降水预报 API 优化城市水利管理?

引言 降水预报对于城市水利管理部门来说至关重要&#xff0c;它可以帮助管理者及时了解当地的降雨情况&#xff0c;以便更好地管理城市水利设施&#xff0c;保障公共安全。然而&#xff0c;传统的降水预报数据一般只提供每小时或每3小时的粗略预报数据&#xff0c;无法满足城市…

ICV: 全球QRNG产业规模在2030年有望突破200亿美元

近日&#xff0c;专注于前沿科技领域的国际咨询机构ICV发布了《全球量子随机数发生器的产业研究报告》&#xff0c;从多个角度对QRNG的市场进行预测。 QRNG 是解决与随机数相关的问题&#xff08;例如密码解决方案&#xff09;的重要硬件来源。 QRNG 是随着量子物理技术的发展…

2023年6月DAMA-CDGA/CDGP数据治理认证报名请尽早啦!

6月18日DAMA-CDGA/CDGP数据治理认证考试开放报名中&#xff01; 考试开放地区&#xff1a;北京、上海、广州、深圳、长沙、呼和浩特、杭州、南京、济南、成都、西安。其他地区凑人数中… DAMA-CDGA/CDGP数据治理认证开班时间&#xff1a;5月7日 DAMA认证为数据管理专业人士提供…

项目管理:项目进度跟踪的好处有哪些?

项目进度跟踪主要针对项目计划、任务和项目成员三个方面&#xff0c;即为了了解整个项目计划完成情况、了解项目的实际进展情况、解成员工作完成情况。 项目跟踪可以证明计划是否可执行&#xff0c;可以说明计划是否可以被完成。 在项目执行过程中&#xff0c;我们也可以通过跟…

windows安装node.js和vue3.x

目录 下载并安装node配置环境变量配置淘宝镜像源安装webpack全局打包工具安装cnpm安装vue-cli 3.xcnpm问题警告的解决办法 下载并安装node 1&#xff0c;下载nodejs 直接从node.js官网下载&#xff1a;https://nodejs.org/en/download 根据自己电脑的版本选择32位或者64位&…

智慧城市3d可视化管理大屏系统有效提高服务质量和效率

随着新一代信息技术飞速融入传统产业&#xff0c;农业数字化、网络化、智能化逐步成为农业现代化发展的基石。实现农业生产环境的智能感知、智能预警、智能决策、智能分析等功能&#xff0c;为农业生产提供精准化保障、高质量运营水平、智能化决策支撑。 3D可视化智慧管理 1&am…

中断-STM32

中断-STM32 中断:在主程序运行过程中&#xff0c;出现了特定的中断触发条件 (中断源)&#xff0c;使得CPU暂停当前正在运行的程序转而去处理中断程序处理完成后又返回原来被暂停的位置继续运行。 中断优先级:当有多个中断源同时申请中断时&#xff0c;CPU会根据中断源的轻重缓…

【Halcon】 Halcon 22.11 安装详细教程

文章目录 1安装2 获取许可证 license2.1 license下载2.2 激活 license放置在相应文件夹下3 DLT 安装1安装 1.解压安装包 2.打开运行 exe 程序 跳转至页面 点击“可获得的”,并安装选择: AVAILABLE ->INSTALL 可获得的 ->安装

云计算中的边缘计算技术及其应用

章节一&#xff1a;云计算和边缘计算的简介 随着互联网的发展&#xff0c;数据中心的规模不断扩大&#xff0c;云计算也成为了越来越受欢迎的计算模式。但是&#xff0c;云计算存在着一些问题&#xff0c;比如延迟较高&#xff0c;网络瓶颈&#xff0c;数据隐私和安全性等等。…

Wikidata 模型分析+实体抽取+数据处理

Wikidata 数据分析与处理 需求&#xff1a;Wikidata 数据描述了很多实体&#xff0c;以及实体属性。比如某一个公司/组织/机构名称是&#xff1a;阿里巴巴&#xff0c;对数据内该组织的相关属性进行观察、分析、治理、抽取等&#xff0c;最后用图数据库进行存储和展示其关系&am…

蓝牙资讯|苹果与谷歌起草蓝牙定位追踪设备行业规范

苹果与谷歌于当地时间5月2日联合提交了一份行业规范草案&#xff0c;以帮助应对蓝牙定位追踪设备遭滥用的问题。目前已有包括三星在内的追踪设备制造厂商宣布支持该草案。 据了解&#xff0c;苹果与谷歌此次联合提交的行业规范草案将云熙蓝牙定位追踪设备兼容跨iOS以及Android平…

asp.net+sqlserver漫画绘本借阅管理系统

摘 要1 第1章 系统概述5 1.1 研究背景5 1.2 研究的意义5 1.3 主要研究内容5 第2章 系统开发环境7 2.1 ASP.NET概述7 2.2 动态网站技术介绍8 2.3 数据库技术8 第3章 需求分析9 3.1 需求分析9 3.1.1 功能需求9 3.2 可行性分析9 3.2.1 可行性分析9 3.2.2 技术可行性9 3.2.3 运行可…

详解c++---模拟实现stack和queue

目录标题 设计模式stack的模拟实现准备工作各种函数的实现 queue的模拟实现准备工作queue的接口实现 deque的介绍为什么会有dequedeque的原理deque的迭代器为什么使用deque 设计模式 设计模式分为两个&#xff1a;迭代器模式和适配器模式 第一个&#xff1a;迭代器模式 迭代器…

FT2000+ qemu kvm 64C64G 通过频繁设置CPU online 状态导致虚拟机openEuler 操作系统假死测试用例2

前文&#xff1a; https://hknaruto.blog.csdn.net/article/details/130408240 测试程序 /** tcti.cpp参考&#xff1a; https://www.cnblogs.com/organic/p/17321523.htmlg -stdc11 -lpthread trigger_cgroup_timer_inactive.cpp -o inactive_timer ./inactive_timer 100000…

【刷题】141. 环形链表

141. 环形链表 一、题目描述二、示例三、实现思考总结 141. 环形链表 一、题目描述 给你一个链表的头节点 head &#xff0c;判断链表中是否有环。 如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次到达&#xff0c;则链表中存在环。 为了表示给定链表中的环…

Spring是什么?关于Spring家族

初识Spring 什么是Spring&#xff1f; Spring是一个开源的Java企业级应用程序开发框架&#xff0c;由Rod Johnson于2003年创建&#xff0c;并在接下来的几年里得到了广泛的发展和应用。它提供了一系列面向对象的编程和配置模型&#xff0c;支持开发各种类型的应用程序&#x…

晒出新高度?2023夏季小红书防晒趋势前瞻

夏日将临&#xff0c;防晒需求激增&#xff0c;进入市场旺季。今年防晒赛道朝着“防护升级&#xff0c;多面兼顾”大势发展。 哪些趋势值得关注&#xff1f;本期&#xff0c;千瓜将通过小红书数据分析和笔记内容洞察&#xff0c;为品牌提供数据支持和方向参考。 月增长高达501.…

QProgressBar详解

QProgressBar详解 [1] QProgressBar详解1.QProgressBar简述2.常用方法3.示例&#xff0c;比较进度条4.设置样式表 [1] QProgressBar详解 原文链接&#xff1a;https://blog.csdn.net/wzz953200463/article/details/125530997 1.QProgressBar简述 QProgressBar提供了一个水平…