【数据结构】之优先级队列(堆)

news2024/9/24 18:24:14

文章目录

  • 一、优先级队列的概念
  • 二、优先级队列的模拟实现
    • 1.堆的存储
    • 2.堆的创建
    • 3.代码的实现


一、优先级队列的概念

队列是一种先进先出(FIFO)的数据结构,但有些情况下,操作的数据可能带有优先级,一般出队列时,可能需要优先级高的元素先出队列
在这种情况下,数据结构应该提供两个最基本的操作,一个是返回最高优先级对象,一个是添加新的对象。这种数据结构就是优先级队列(Priority Queue)
PriorityQueue底层使用了堆这种数据结构,而堆实际就是在完全二叉树的基础上进行了一些调整

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

1.堆的存储

堆的性质:
(1).堆中某个节点的值总是不大于或不小于其父节点的值;
(2).堆总是一棵完全二叉树
堆的存储方式有:小根堆、大根堆
小根堆:根节点总是比左右子节点小
在这里插入图片描述
大根堆:根节点总是比左右子节点大
在这里插入图片描述
堆是一棵完全二叉树,因此可以用层序存储的方式进行,存储在数组当中
将元素存储到数组后,在以实现树的方式对堆进行实现。设 i 结点为数组中的下标,则有以下特点:
(1).如果i为0,则i表示的节点为根节点,否则i节点的双亲节点为 (i - 1)/2
(2).如果2 * i + 1 小于节点个数,则节点i的左孩子下标为2 * i + 1,否则没有左孩子
(3).如果2 * i + 2 小于节点个数,则节点i的右孩子下标为2 * i + 2,否则没有右孩子

2.堆的创建

这里我们创建的堆是大根堆的形式
大根堆的特点是根节点的元素始终比左右子树都要大,所以我们要调整这棵树,是需要将较小的根的从上面下降至下面,简称向下调整。这里,就需要定义两个变量,一个找到最后一个数组元素即 child 结点,另一个则要找到这个结点的父节点即 parent 结点
我们以集合{ 27,15,19,18,28,34,65,49,25,37 }中的数据,将其创建成大根堆
在这里插入图片描述
大致操作如下图,以 第一次调整 数字 37 为例实现:
在这里插入图片描述

3.代码的实现

public class TestHeap {
    public int[] elem;
    public int usedSize;
    //对数组进行初始化
    public TestHeap() {
        this.elem = new int[10];
    }
    //赋值
    public void initElem(int[] array) {
        for (int i = 0; i < array.length; i++) {
            elem[i] = array[i];
            usedSize++;
        }
    }
    //创建堆
    public void createBigHeap() {
        for (int parent = (usedSize-1-1)/2; parent >=0 ; parent--) {
            //向下调整
           siftDown(parent,usedSize);
        }
    }
    private void siftDown(int parent,int end) {
        //孩子结点
        int child = 2*parent+1;
        while (child < end) {
            //前一个判断防止越界,后一个判断找左右孩子的最大值
            if(child+1 < end && elem[child] < elem[child+1]) {
                child++;
            }
            //找到最大值之后与parent进行比较并交换
            if(elem[child] > elem[parent]) {
                swap(parent,child);
                //交换之后还要保证下面的树也是大根堆
                parent = child;
                child = 2*parent+1;
            }else {
                break;
            }
        }
    }
    private void swap(int i,int j) {
        int tmp = elem[i];
        elem[i] = elem[j];
        elem[j] = tmp;
    }
}

以下是大根堆创建完成的结果:
在这里插入图片描述
插入操作:
在进行插入操作时我们要考虑以下几个问题:
(1).在插入元素时我们要注意数组是否已经满了
(2).插入元素的位置是插入在数组的末尾,即树的最后一个结点
(3).插入的元素要进行向上移动的操作

    public void offer(int val) {
        //判断数组是否满了,满了就进行扩容
        if(isFull()) {
            this.elem = Arrays.copyOf(elem,2*elem.length);
        }
        //在末尾插入元素
        elem[usedSize] = val;
        usedSize++;
        //进行向上调整
        siftUp(usedSize-1);
    }
    public void siftUp(int child) {
        //要插入结点的父亲结点 
        int pareat = (child-1)/2;
        while (child > 0) {
            if(elem[child] > elem[pareat]) {
                swap(child,pareat);
                child = pareat;
                pareat = (child-1)/2;
            }else {
                break;
            }
        }
    }
    public boolean isFull() {
        return usedSize == elem.length;
    }

删除操作:
删除元素要注意:
删除的是堆顶的元素,将第一个元素与最后一个元素进行交换,然后向下调整

    public int poll() {
        //把要删除的结点和最后一个结点进行交换
        int tmp = elem[0];
        swap(0,usedSize-1);
        usedSize--;
        //对交换后的元素进行向下调整
        siftDown(0,usedSize);
        return tmp;
    }

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

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

相关文章

wireshark抓取localhost(127.0.0.1)数据包

打开wireshark中&#xff0c;在"capture"菜单中&#xff0c;选择"interfaces"子菜单&#xff0c;在列出的接口中选中"Adapter for loopback traffic capture"即可。 必须安装了Npcap才有此选项&#xff0c;否则需要重新安装wireshark。 抓包截图…

Windows 10 合并磁盘分区 (G and H)

Windows 10 合并磁盘分区 [G and H] 1. 设备和驱动器2. 计算机 -> 管理 -> 存储 -> 磁盘管理3. 删除卷4. 新建简单卷5. 设备和驱动器References 1. 设备和驱动器 2. 计算机 -> 管理 -> 存储 -> 磁盘管理 3. 删除卷 H: -> right-click -> 删除卷 H: 变…

c语言经典测试题10

1.题1 int fun( int x) {int n 0;while (x 1){n;x x | (x 1);}return n; } int main() {int ret fun(2014);printf("%d", ret);return 0; } 上述代码运行结果是什么呢&#xff1f; 我们来分析一下&#xff1a;这里的fun函数有一个while循环&#xff0c;其判断…

uniApp 调整小程序 单个/全部界面横屏展示效果

我们打开uni项目 小程序端运行 默认是竖着的一个效果 我们打开项目的 pages.json 给需要横屏的界面 的 style 属性 加上 "mp-weixin": {"pageOrientation": "landscape" }界面就横屏了 如果是要所有界面都横屏的话 就直接在pages.json 的 gl…

14-Linux部署Hadoop集群

Linux部署Hadoop集群 简介 1&#xff09;Hadoop是一个由Apache基金会所开发的分布式系统基础架构。 2&#xff09;主要解决&#xff0c;海量数据的存储和海量数据的分析计算问题。 Hadoop HDFS 提供分布式海量数据存储能力 Hadoop YARN 提供分布式集群资源管理能力 Hadoop…

Django后端开发——cookies和session

文章目录 参考资料会话保持Cookiesviews.pyurls.py Sessionviews.pyurls.py Cookies和session对比 参考资料 B站网课&#xff1a;点击蓝色字体跳转 或复制链接至浏览器&#xff1a;https://www.bilibili.com/video/BV1vK4y1o7jH/?p29&spm_id_from333.1007.top_right_bar_…

Android Gradle开发与应用 (四) : Gradle构建与生命周期

1. 前言 前几篇文章&#xff0c;我们对Gradle中的基本知识&#xff0c;包括Gradle项目结构、Gradle Wrapper、GradleUserHome、Groovy基础语法、Groovy语法概念、Groovy闭包等知识点&#xff0c;这篇文章我们接着来介绍Gradle构建过程中的知识点。 2. Project : Gradle中构建…

Linux - 基本开发工具

1、软件包管理器 yum 1.1、什么是软件包 在Linux下安装软件, 一个通常的办法是下载到程序的源代码, 并进行编译, 得到可执行程序但是这样太麻烦了, 于是有些人把一些常用的软件提前编译好, 做成软件包(可以理解成windows上的安装程序)放在一个服务器上, 通过包管理器可以很方…

接口测试(全)

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 关注公众号【互联网杂货铺】&#xff0c;回复 1 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 大多数人对于接口测试都觉得是一种高大上的测试&#xff0c;觉得…

Flutter开发之CupertinoApp

Flutter开发之CupertinoApp 最近由于使用Flutter编程更多&#xff0c;使用Flutter更顺手&#xff0c;相对于其他前端框架来说&#xff0c;Flutter在跨平台、响应式UI、自绘引擎、即插即用的组件和庞大的社区生态支持方面有更大的优势&#xff1b;Flutter拥有更低的学习成本&am…

前端monorepo大仓共享复杂业务组件最佳实践

一、背景 在 Monorepo 大仓模式中&#xff0c;我们把组件放在共享目录下&#xff0c;就能通过源码引入的方式实现组件共享。越来越多的应用愿意走进大仓&#xff0c;正是为了享受这种组件复用模式带来的开发便利。这种方式可以满足大部分代码复用的诉求&#xff0c;但对于复杂…

AutoEncoder和 Denoising AutoEncoder学习笔记

参考&#xff1a; 【1】 https://lilianweng.github.io/posts/2018-08-12-vae/ 写在前面&#xff1a; 只是直觉上的认识&#xff0c;并没有数学推导。后面会写一篇&#xff08;抄&#xff09;大一统文章&#xff08;概率角度理解为什么AE要选择MSE Loss&#xff09; TOC 1 Au…

Java进阶-IO(1)

进入java IO部分的学习&#xff0c;首先学习IO基础&#xff0c;内容如下。需要了解流的概念、分类还有其他一些如集合与文件的转换&#xff0c;字符编码问题等&#xff0c;这次先学到字节流的读写数据&#xff0c;剩余下次学完。 一、IO基础 1、背景 1.1 数据存储问题 变量…

Day21-磁盘管理之raid及分区

Day21-磁盘管理之raid及分区 1 Raid技术1.1 什么是Raid?1.2 为什么服务器需要Raid?1.3 什么是Raid级别?1.4 Raid有哪些实现方式&#xff1f;1.5 什么是RAID0&#xff1f;&#xff08;图&#xff09;1.6 什么是RAID1&#xff1f;&#xff08;图&#xff09;1.7 什么是RAID5&a…

Python爬虫Cookies 池的搭建

Cookies 池的搭建 很多时候&#xff0c;在爬取没有登录的情况下&#xff0c;我们也可以访问一部分页面或请求一些接口&#xff0c;因为毕竟网站本身需要做 SEO&#xff0c;不会对所有页面都设置登录限制。 但是&#xff0c;不登录直接爬取会有一些弊端&#xff0c;弊端主要有…

[HackMyVM] 靶场 Wave

kali:192.168.56.104 主机发现 arp-scan -l # arp-scan -l Interface: eth0, type: EN10MB, MAC: 00:0c:29:d2:e0:49, IPv4: 192.168.56.104 Starting arp-scan 1.10.0 with 256 hosts (https://github.com/royhills/arp-scan) 192.168.56.1 0a:00:27:00:00:05 (Un…

学习助手:借助AI大模型,学习更高效!

在当今的数字时代&#xff0c;人工智能&#xff08;AI&#xff09;的崛起已经彻底改变了我们获取信息、处理数据以及学习新知识的方式。AI大模型&#xff0c;特别是如OpenAI开发的GPT-4这类先进的技术&#xff0c;已成为学习和教育领域的一大助力。本文旨在探索如何借助AI大模型…

tritonserver学习之八:redis_caches实践

tritonserver学习之一&#xff1a;triton使用流程 tritonserver学习之二&#xff1a;tritonserver编译 tritonserver学习之三&#xff1a;tritonserver运行流程 tritonserver学习之四&#xff1a;命令行解析 tritonserver学习之五&#xff1a;backend实现机制 tritonserv…

javaWebssh票据管理系统myeclipse开发mysql数据库MVC模式java编程计算机网页设计

一、源码特点 java ssh票据管理系统是一套完善的web设计系统&#xff08;系统采用ssh框架进行设计开发&#xff09;&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模 式开发。开发环境为TOMCAT7.0,My…

Vue+SpringBoot打造高校大学生创业管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 系统公告模块2.2 创业项目模块2.3 创业社团模块2.4 政府政策模块2.5 创业比赛模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 系统公告表3.2.2 创业项目表3.2.3 创业社团表3.2.4 政策表 四、系统展示五、核心代码5.…