数据结构:优先级队列—堆

一、优先级队列

1、优先级队列概念

优先级队列,听名字我们就知道他是一种队列,队列在前面我们已经学习过了,它是一种先进先出的数据结构,但是在特殊的情况下,我们我们队列中元素是带有一定优先级的它需要比我们此时的队头元素,更先的出队列,或者更先的入队列

比如,当我们刚进入游戏的时候,突然有人来敲门,在这种情况下,我们是不是应该先去开门,虽然我们是先进的游戏,但是我们应该先去开门。

或者,当我们要乘坐飞机时,我们是经济舱的乘客,现在我们正在排队检票,下一个就是你,但是这时来了个头等舱的人,他肯定是要比我们先进的。

在这种情况下,数据结构应该提供两个最基本的操作,一个是返回最高优先级对象,一个是添加新的对象。这种数据结构就是优先级队列(PriorityQueue)

2、堆的概念

我们在前面了解了完全二叉树的概念,每一层的节点都是从左往右的,依次排列,中间不能空着元素。这就是完全二叉树的概念,那么完全二叉树跟我们今天要讲的堆又有什么关系呢?

其实,堆是一个(特殊的)完全二叉树,每个父节点都不大于或者不小于自己的孩子节点,因此我们将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆

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

这就是堆的存储。因此从逻辑上来说,堆是一棵完全二叉树,从存储底层来说,堆底层是一个数组。

二、优先级队列的模拟实现

1、堆的存储方式

从上述堆的概念可知,堆是一棵完全二叉树,因此可以层序遍历的规则采用顺序的方式来高效存储

但是我们要注意,如果此时我们不是堆,而是一棵非完全二叉树,则不适合使用顺序方式进行存储,因为为了能够还原二叉树,空间中必须要存储空节点,就会导致空间利用率比较低

2、堆的创建

根据上述的概念知道,堆有两种:大根堆和小根堆,但如果此时我们给出一个大小顺序不同的集合,我们该如何创建一个大根堆或小根堆呢?

这就要引出我们的一种调整方法:向下调整

(1)堆向下调整

我们以这个集合{ 27,15,19,18,28,34,65,49,25,37}为例,我们先利用层序遍历的方式画出他的二叉树图。

我们希望将这棵二叉树调整成一个大根堆,但根据上图我们发现,他的最后的根节点和左右两边,并不满足一个大根堆的形式,因此我们需要将他进行调整,我们将最后根节点左右两边最大的一个结点与他进行交换,这样我们的最后根节点和他的左右两边就形成了一个大根堆,而这样一个往下调整的过程我们就称它为向下调整,但是我们发现进行调整之后,我们有的之后的根结点和他的左右两边,他就不是一个大根堆了因此我们需对他进行调整,因此在这里我们就得出了我们向下调整的过程

1.让parent标记需要调整的节点,child标记parent的左孩子(注意:parent如果有孩子一定先是有左孩子)

2. 如果parent的左孩子存在,即:child< usesize 进行以下操作,直到parent的左孩子不存在如果左孩子存在判断parent右孩子是否存在,存在找到左右孩子中最小的孩子,让child进行标记,然后将parent与较小的孩子child比较,如果:

  (1)parent大于较大的孩子child,调整结束

  (2)否则交换parent与较大的孩子child,交换完成之后,parent中小的元素向下移动,可能导致子树不满足对的性质,因此需要继续向下调整,即parent=child;child=parent*2+1; 然后继续步骤2。

 public void createHeap(){
//我们从下往上走 ,找倒数第⼀个⾮叶⼦节点,从该节点位置开始往前⼀直到根节点,遇到⼀个节点,应⽤向下调整
        for(int parent = (usesize-1-1)/2;parent >=0 ;parent--){
            sifDown(parent,usesize);
        }
    }

    public void sifDown(int parent,int usesize){
  // child先标记parent的左孩⼦,因为parent可能右左没有右
        int child = 2*parent + 1;
        while(child < usesize){
  // 如果右孩⼦存在,找到左右孩⼦中较⼩的孩⼦,⽤child进⾏标记
            if(child+1 < usesize && elem[child] < elem[child+1]){
                child++;
            }
 // 如果双亲⽐其最⼩的孩⼦还大,说明该结构已经不满⾜堆的特性了,将双亲与较⼩的孩⼦交换
            if(elem[child] > elem[parent]){
                swap(child,parent);
 // parent中⼤的元素往下移动,可能会造成⼦树不满⾜堆的性质,因此需要继续向下调整
                parent = child;
                child = 2*parent + 1;
            }else{
                break;
            }
        }
    }

(2)堆向上调整:堆的插入

堆的插入总共需要两个步骤:

1. 先将元素放到堆的最后(注意:空间不够时需要扩容)

2. 将最后新插入的节点向上调整,直到满足堆的性质

在这里我们引入了一个新的方法:向上调整,他其实跟我们的向下调整是一样的只是向下调整是传入父亲结点,再去求孩子结点进行判断,而向上调整是传入孩子结点,求父亲结点进行判断

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

    public  void sifUp(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;
            }
        }
    }

(3)堆的删除

注意:堆的删除我们要删除的是堆顶元素。

堆的删除总共需要三个步骤:

1. 将堆顶元素对堆中最后一个元素交换

2. 将堆中有效数据个数减少一个

3. 对堆顶元素进行向下调整

 public  int poll(int val){
        if(empty()){
            return -1;
        }
        int oldVale = elem[0];
        swap(0,usesize-1);
        usesize--;
        sifDown(0,usesize);
        return oldVale;
    }

完整代码

public class TestHeap {
    public int[] elem;
    public int usesize;
    public TestHeap(){
        elem = new int[10];
    }
    public void len(int[] arr){
        for (int i = 0; i < arr.length; i++) {
            elem[i] = arr[i];
            usesize++;
        }
    }
    public void createHeap(){
        for(int parent = (usesize-1-1)/2;parent >=0 ;parent--){
            sifDown(parent,usesize);
        }
    }

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

    public void swap(int i,int j){
        int tmp = elem[i];
        elem[i] = elem[j];
        elem[j] = tmp;
    }
    public void offer(int val){
        if(isFull()){
            elem = Arrays.copyOf(elem,2*elem.length);
        }
        elem[usesize] = val;
        sifUp(usesize);
        usesize++;
    }

    public  void sifUp(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;
            }
        }
    }
    public  int poll(int val){
        if(empty()){
            return -1;
        }
        int oldVale = elem[0];
        swap(0,usesize-1);
        usesize--;
        sifDown(0,usesize);
        return oldVale;
    }

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

    public  boolean empty(){
        return usesize == 0;
    }

    public int peekHeap(){
        return elem[0];
    }

    


}

好了今天的分享就到这里了,还请大家多多关注,我们下一篇见!

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

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

相关文章

北大:三阶段学习优化多模态推理问答

&#x1f4d6;标题&#xff1a;ReasVQA: Advancing VideoQA with Imperfect Reasoning Process &#x1f310;来源&#xff1a;arXiv, 2501.13536 &#x1f31f;摘要 &#x1f538;视频问答&#xff08;VideoQA&#xff09;是一项具有挑战性的任务&#xff0c;需要理解视频中…

从零开始:用Qt开发一个功能强大的文本编辑器——WPS项目全解析

文章目录 引言项目功能介绍1. **文件操作**2. **文本编辑功能**3. **撤销与重做**4. **剪切、复制与粘贴**5. **文本查找与替换**6. **打印功能**7. **打印预览**8. **设置字体颜色**9. **设置字号**10. **设置字体**11. **左对齐**12. **右对齐**13. **居中对齐**14. **两侧对…

Jason配置环境变量

jason官网 https://jason-lang.github.io/ https://github.com/jason-lang/jason/releases 步骤 安装 Java 21 或更高版本 安装 Visual Studio Code 根据操作系统&#xff0c;请按照以下具体步骤操作 视窗 下载 Jason 的最新版本&#xff0c;选择“jason-bin-3.3.0.zip”…

机器学习--概览

一、机器学习基础概念 1. 定义 机器学习&#xff08;Machine Learning, ML&#xff09;&#xff1a;通过算法让计算机从数据中自动学习规律&#xff0c;并利用学习到的模型进行预测或决策&#xff0c;而无需显式编程。 2. 与编程的区别 传统编程机器学习输入&#xff1a;规…

如何使用SliverGrid组件

文章目录 1 概念介绍2 使用方法3 示例代码 我们在上一章回中介绍了SliverList组件相关的内容&#xff0c;本章回中将介绍SliverGrid组件.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1 概念介绍 我们在本章回中介绍的SliverGrid组件是一种网格类组件&#xff0c;主要用来…

大模型培训讲师老师叶梓分享:DeepSeek多模态大模型janus初探

以下视频内容为叶梓分享DeepSeek多模态大模型janus的部署&#xff0c;并验证其实际效果&#xff0c;包括图生文和文生图两部分。 叶梓老师人工智能培训分享DeepSeek多模态大模型janus初探 DeepSeek 的多模态大模型 Janus 是一款强大的 AI 模型&#xff0c;专注于图像和文本的多…

一文掌握ADB的安装及使用

文章目录 一、什么是ADB&#xff1f;二、 安装ADB2.1 下载ADB2.2 配置环境变量 三、连接Android设备四、 常用ADB命令五、ADB高级功能5.1 屏幕截图和录制5.2 模拟按键输入5.3 文件管理5.4 系统设置管理5.5 系统操作指令5.6 日志操作指令5.7 APK操作指令5.8 设备重启和恢复 六、…

【机器学习与数据挖掘实战】案例11:基于灰色预测和SVR的企业所得税预测分析

【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈机器学习与数据挖掘实战 ⌋ ⌋ ⌋ 机器学习是人工智能的一个分支,专注于让计算机系统通过数据学习和改进。它利用统计和计算方法,使模型能够从数据中自动提取特征并做出预测或决策。数据挖掘则是从大型数据集中发现模式、关联…

bat脚本实现自动化漏洞挖掘

bat脚本 BAT脚本是一种批处理文件&#xff0c;可以在Windows操作系统中自动执行一系列命令。它们可以简化许多日常任务&#xff0c;如文件操作、系统配置等。 bat脚本执行命令 echo off#下面写要执行的命令 httpx 自动存活探测 echo off httpx.exe -l url.txt -o 0.txt nu…

Kafka下载

一、Kafka下载 下载地址&#xff1a;https://kafka.apache.org/downloads 二、Kafka安装 因为选择下载的是 .zip 文件&#xff0c;直接跳过安装&#xff0c;一步到位。 选择在任一磁盘创建空文件夹&#xff08;不要使用中文路径&#xff09;&#xff0c;解压之后把文件夹内容…

学习日记-250202

现在开始要继续写我的日记了......&#xff08;也可以当作笔记吧&#xff09; 一.论文 Prompt Transfer for Dual-Aspect Cross Domain Cognitive Diagnosis 主要内容&#xff1a; 主要是加入prompt提示&#xff0c; 为重叠实体设计个性化的提示&#xff0c;为非重叠实体设计共…

【人工智能学习笔记 一】 AI分层架构、基本概念分类与产品技术架构

新的一年2025要对AI以及LLM有个强化的学习&#xff0c;所以第一篇先对整体有个大概的认知&#xff0c;一直分不清LLM和AI的关系&#xff0c;在整个体系里的位置&#xff0c;以及AIGC是什么东西&#xff0c;AI AGENT类似豆包等和大语言模型的具体关系是什么&#xff0c;整个AI的…

git多人协作

目录 一、项目克隆 二、 1、进入克隆仓库设置 2、协作处理 3、冲突处理 4、多人协作分支的推送拉取删除 1、分支推送&#xff08;2种&#xff09; 2、远程分支拉取&#xff08;2种&#xff09; 3、远程分支删除 一、项目克隆 git clone 画船听雨眠/test1 (自定义的名…

线性数据结构:单向链表

放弃眼高手低&#xff0c;你真正投入学习&#xff0c;会因为找到一个新方法产生成就感&#xff0c;学习不仅是片面的记单词、学高数......只要是提升自己的过程&#xff0c;探索到了未知&#xff0c;就是学习。 目录 一.链表的理解 二.链表的分类&#xff08;重点理解&#xf…

linux下ollama更换模型路径

Linux下更换Ollama模型下载路径指南   在使用Ollama进行AI模型管理时&#xff0c;有时需要根据实际需求更改模型文件的存储路径。本文将详细介绍如何在Linux系统中更改Ollama模型的下载路径。 一、关闭Ollama服务   在更改模型路径之前&#xff0c;需要先停止Ollama服务。…

影视文件大数据高速分发方案

在当今的数字时代&#xff0c;影视行业的内容创作和传播方式经历了翻天覆地的变化。随着4K、8K高清视频的普及&#xff0c;以及虚拟现实(VR)和增强现实(AR)技术的发展&#xff0c;影视文件的数据量正以前所未有的速度增长。这就要求行业内的参与者必须拥有高效的大数据传输解决…

【AI】探索自然语言处理(NLP):从基础到前沿技术及代码实践

Hi &#xff01; 云边有个稻草人-CSDN博客 必须有为成功付出代价的决心&#xff0c;然后想办法付出这个代价。 目录 引言 1. 什么是自然语言处理&#xff08;NLP&#xff09;&#xff1f; 2. NLP的基础技术 2.1 词袋模型&#xff08;Bag-of-Words&#xff0c;BoW&#xff…

HTMLCSS :下雪了

这段代码创建了一个动态的雪花飘落加载动画&#xff0c;通过 CSS 技术实现了雪花的下落和消失效果&#xff0c;为页面添加了视觉吸引力和动态感。 大家复制代码时&#xff0c;可能会因格式转换出现错乱&#xff0c;导致样式失效。建议先少量复制代码进行测试&#xff0c;若未能…

Android 音视频编解码 -- MediaCodec

引言 如果我们只是简单玩一下音频、视频播放&#xff0c;那么使用 MediaPlayer SurfaceView 播放就可以了&#xff0c;但如果想加个水印&#xff0c;加点其他特效什么的&#xff0c;那就不行了&#xff1b; 学习 Android 自带的硬件码类 – MediaCodec。 MediaCodec 介绍 在A…

一文了解阿里的 Qwen2.5 模型

最近被DeepSeek刷屏了&#xff0c;但是在之外阿里在2025年1月28日推出了Qwen 2.5 Max模型。 Qwen2.5-Max 的特点&#xff1a;大规模的 MoE 模型&#xff0c;预训练于超 20 万亿 tokens&#xff0c;并经过 SFT 和 RLHF 后训练。 性能表现&#xff1a;在多个基准测试中与领先模型…