知识改变命运 数据结构【优先级队列(堆)】

优先级队列(堆)

  • 1:堆概念
  • 2:堆的创建(以小根堆为例)
  • 3:堆的插入与删除
    • 3.1 堆的插入
    • 3.2堆的删除
  • 4:oj练习
  • 5:堆排序
  • 6接口介绍(底层代码的查看)
    • 6.1常用三种构造方法

前言:队列是一种先进先出的数据结构,但是某时候有一些数据有优先级,比如打游戏时候突然来个电话。在这种情况下,数据结构应该提供两个最基本的操作,一个是返回最高优先级对象,一个是添加新的对象。这种数据结构就是优先级队列(Priority Queue)。

1:堆概念

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

堆的一些特征:
1:堆是一颗完全二叉树
2:堆采用的是层序规则顺序存储结构,因为堆是一颗完全二叉树,非完全二叉树不适合顺序存储,会造成空间的浪费
2:堆的子节点的值不大于或者不小于其父亲结点的值
以小根堆为例:
在这里插入图片描述

一些重要的二叉树性质:
在这里插入图片描述

2:堆的创建(以小根堆为例)

问题:对于集合{ 27,15,19,18,28,34,65,49,25,37 }中的数据,如果将其创建成堆呢?
我自己理解画的图的和写的代码:
在这里插入图片描述

public class TestHeap {public int usedSize;public int []elem;public TestHeap() {this.elem = new int[10];}public void initElem(int[] array) {for (int i = 0; i < array.length; i++) {this.elem[i] = array[i];usedSize++;}}// 时间复杂度:O(N)public void  createHeap() {//每个父亲节点for (int parent=(usedSize-1-1)/2;parent>=0;parent--) {sitfDown(parent,usedSize-1);//调整}}时间复杂度:O(log(n))private void sitfDown(int parent, int i) {int child=2*parent+1;//先求出左孩子结点while(child<=i) { //结束条件child<useSize这里传过来的是usedSize-1if ((child+1<=i)&&elem[child]>elem[child+1]) {child++;//判断左右孩子的大小,如果左边大,就调整为右孩子结点}//判断父结点和子结点大小if(elem[parent]>elem[child]) {swap(elem,parent,child);//如果父节点大于就交换//继续往下调整parent=child;child=2*parent+1;}else  {//如果父子节点小于子结点之间结束循环,因为是从最后一颗树调整,所有下面的树就是小根堆。break;}}}private void swap(int array[],int parent, int child) {int temp=array[parent];array[parent]=array[child];array[child]=temp;}
}

注意事项:
子结点必须已经是小根堆
在调整以parent为根的二叉树时,必须要满足parent的左子树和右子树已经是堆了才可以向下调整。
这里主要注意一下结束条件,还要就是如果父亲结点比子结点小,直接跳出循环的理解,因为当父亲结点小于子节点时候,子节点本来已经就是小根堆了,父亲结点的值就不可能比子节点的值再小了。

建堆的时间复杂度
因为堆是完全二叉树,而满二叉树也是完全二叉树,此处为了简化使用满二叉树来证明(时间复杂度本来看的就是近似值,多几个节点不影响最终结果):
在这里插入图片描述
向上建堆的时间复杂度
在这里插入图片描述

3:堆的插入与删除

3.1 堆的插入

 public void offer(int val) {if(isFull()==true) {elem= Arrays.copyOf(elem,2*elem.length);}elem[usedSize]=val;upDown(usedSize,elem);usedSize++;}private void upDown(int usedSize, int[] elem) {int parent=(usedSize-1)/2;int child=usedSize;while(parent>=0) {if(elem[child]<elem[parent]) {swap(elem,parent,child);child=parent;parent=(child-1)/2;} else {break;}}}private boolean isFull() {return elem.length==usedSize;}
}

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

  1. 先将元素放入到底层空间中(注意:空间不够时需要扩容)
  2. 将最后新插入的节点向上调整,直到满足堆的性质
  3. 在这里插入图片描述

3.2堆的删除

 public void  poll() {if (isEmpty()) {return;}swap(elem,0,usedSize-1);usedSize--;siftDown(0,usedSize-1);//调整}private boolean isEmpty() {return usedSize==0;}
}

注意:堆的删除一定删除的是堆顶元素。具体如下:

  1. 将堆顶元素对堆中最后一个元素交换
  2. 将堆中有效数据个数减少一个
  3. 对堆顶元素进行向下调整
    在这里插入图片描述

4:oj练习

top-k问题:最大或者最小的前k个数据。比如:世界前500强公司
top-k问题:最小的K个数
在这里插入图片描述
优化:
topk方法解决。

 public static int [] findmax(int []array,int k) {PriorityQueue<Integer> priorityQueue =new PriorityQueue<>();//k*log(K)for (int i = 0; i <k ; i++) {priorityQueue.offer(array[i]);}//(n-k)*log(k)for (int i = k; i <array.length ; i++) {int peek=priorityQueue.peek();if(peek<array[i]) {priorityQueue.poll();priorityQueue.offer(array[i]);}}int []elem=new int[k];for (int i = 0; i <k ; i++) {elem[i]=priorityQueue.poll();}return elem;}

在这里插入图片描述

5:堆排序

堆排序即利用堆的思想来进行排序,总共分为两个步骤:

  1. 建堆
    升序:建大堆
    降序:建小堆
  2. 利用堆删除思想来进行排序
    建堆和堆删除中都用到了向下调整,因此掌握了向下调整,就可以完成堆排序。
    在这里插入图片描述

6接口介绍(底层代码的查看)

PriorityQueue的特性
Java集合框架中提供了PriorityQueue和PriorityBlockingQueue两种类型的优先级队列,PriorityQueue是线程不安全的,PriorityBlockingQueue是线程安全的
在这里插入图片描述
关于PriorityQueue的使用要注意:

  1. 使用时必须导入PriorityQueue所在的包,即:
    import java.util.PriorityQueue;
    1. PriorityQueue中放置的元素必须要能够比较大小,不能插入无法比较大小的对象,否则会抛出
      ClassCastException异常
  2. 不能插入null对象,否则会抛出NullPointerException
  3. 没有容量限制,可以插入任意多个元素,其内部可以自动扩容(自动扩容)
  4. 插入和删除元素的时间复杂度为O(log(n));
  5. PriorityQueue底层使用了堆数据结构
  6. PriorityQueue默认情况下是小堆—即每次获取到的元素都是最小的元素

6.1常用三种构造方法

在这里插入图片描述
jdk17
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在堆里面默认的是小堆,如果我们要建大堆就要设置比较器,给堆传入比较器。

// 用户自己定义的比较器:直接实现Comparator接口,然后重写该接口中的compare方法即可
class IntCmp implements Comparator<Integer>{
@Overridepublic int compare(Integer o1, Integer o2) {return o2-o1;}
}
public class TestPriorityQueue {public static void main(String[] args) {PriorityQueue<Integer> p = new PriorityQueue<>(new IntCmp());p.offer(4);p.offer(3);p.offer(2);p.offer(1);p.offer(5);System.out.println(p.peek());}
}

在这里插入图片描述
我们再了解一下jdk8的扩容机制

   private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;private void grow(int minCapacity) {int oldCapacity = queue.length;
// Double size if small; else grow by 50%int newCapacity = oldCapacity + ((oldCapacity < 64) ?(oldCapacity + 2) :(oldCapacity >> 1));
// overflow-conscious codeif (newCapacity - MAX_ARRAY_SIZE > 0)newCapacity = hugeCapacity(minCapacity);queue = Arrays.copyOf(queue, newCapacity);}private static int hugeCapacity(int minCapacity) {if (minCapacity < 0) // overflowthrow new OutOfMemoryError();return (minCapacity > MAX_ARRAY_SIZE) ?Integer.MAX_VALUE :MAX_ARRAY_SIZE;}

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

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

相关文章

Hadoop的三种运行模式:单机模式、伪分布式模式和完全分布式模式

单机模式 单机模式是Hadoop最简单的运行模式。在单机模式下&#xff0c;所有Hadoop组件都运行在单个机器上&#xff0c;包括HDFS、MapReduce等。由于只有一个节点参与计算&#xff0c;单机模式适用于开发和测试阶段&#xff0c;不适合用于处理大规模数据。在单机模式下&#xf…

攻防世界----->Replace

前言&#xff1a;做题笔记。 下载 查壳。 upx32脱壳。 32ida打开。 先运行看看&#xff1a; 没有任何反应&#xff1f; 猜测又是 地址随机化(ASLR)---遇见过。 操作参考&#xff1a; 攻防世界----&#xff1e;Windows_Reverse1_dsvduyierqxvyjrthdfrtfregreg-CSDN博客 然后…

UGUI(现成组合控件)

Drop Down Scroll View Scroll Bar size是滚动条的填充程度 Slider 如果设置为静态&#xff0c;那么传入的值始终为自己设置的那个值 Input Field content type为standard时 可以设置line type&#xff0c; 只读不改&#xff0c;就是可以复制&#xff0c;但是你已经不能输入了…

使用.mdf及.ldf恢复SQL SERVER数据库

文章目录 [toc]1.使用.mdf和对应的.ldf文件恢复数据库1.1 将对应的.mdf和.ldf复制到SQL SERVER路径下1.2 打开SSMS 1.使用.mdf和对应的.ldf文件恢复数据库 1.1 将对应的.mdf和.ldf复制到SQL SERVER路径下 一般默认路径是&#xff1a;C:\Program Files\Microsoft SQL Server\MS…

YOLO11改进|注意力机制篇|引入MSCA注意力机制

目录 一、【MSCA】注意力机制1.1【MSCA】注意力介绍1.2【MSCA】核心代码 二、添加【MSCA】注意力机制2.1STEP12.2STEP22.3STEP32.4STEP4 三、yaml文件与运行3.1yaml文件3.2运行成功截图 一、【MSCA】注意力机制 1.1【MSCA】注意力介绍 下图是【MSCA】的结构图&#xff0c;让我…

easyconnect配置wireshark抓包

文章目录 概述过程配置Wireshark抓包 概述 过程 配置Wireshark抓包 首先需要配置虚拟网卡SangforVPN可被Wireshark识别 重启 sc stop npcap sc start npcap# 清空路由表 netsh int ipv4 reset # 查看路由表 route print

企业建站能带来些什么?2024外包建站公司哪家好

目的的话只有企业自己知道&#xff0c;但作用还是有很多的—— 1.塑造企业精神与文化-对内 企业内部不管是否真的存在企业精神和企业文化&#xff0c;在制作网站的过程中都会考虑到这方面的内容&#xff0c;因为这是企业网站内容中不可或缺的一部分。 在企业内部还不存在所谓…

Java中的冒泡排序法

冒泡排序 排序的介绍冒泡排序法代码实现 排序的介绍 冒泡排序法 代码实现 将五个无序&#xff1a;24&#xff0c;69&#xff0c;80&#xff0c;57&#xff0c;13使用冒泡排序法将其排成一个从小到大的有序数列 public class test{public static void main(String[] args){int a…

tensorflow快速入门--如何定义张量、定义网络结构、超参数设置、模型训练???

前言 由于最近学习的东西涉及到tensorflow的使用&#xff0c;故先简单的学习了一下tensorflow中如何定义张量、定义网络结构、超参数设置、模型训练的API调用过程&#xff1b;欢迎大家&#xff0c;收藏关注&#xff0c;本人将持续更新。 文章目录 1、基本操作1、张量基础操作创…

时间序列+Transformer席卷而来,性能秒杀传统,创新性拉满,引爆顶会!

时间序列分析与Transformer模型的结合&#xff0c;已成为深度学习领域的一大趋势。这种结合能够高效捕捉序列中的长期依赖关系&#xff0c;提升时间序列分析和预测的准确性。 时间序列Transformer技术在股票价格预测、气候预测、交通流量预测、设备故障预测、自然语言处理等多…

封装vue-cropper,图片裁剪组件

组件基本使用: 这里的action同时也可以传相对路径&#xff0c;比如封装了axios&#xff0c;那么组件源码里就不能引入元素axios&#xff0c;可以替换为封装的axios。传 action"/file/upload" 源代码&#xff1a; <script setup> import WuyuCropper from /com…

【基础算法总结】字符串篇

目录 一&#xff0c;算法简介二&#xff0c;算法原理和代码实现14.最长公共前缀5.最长回文子串67.二进制求和43.字符串相乘 三&#xff0c;算法总结 一&#xff0c;算法简介 字符串 string 是一种数据结构&#xff0c;它一般和其他的算法结合在一起操作&#xff0c;比如和模拟&…

远程控制软件推荐:亲测好用!

无论是在家办公、技术支持还是远程协助家人&#xff0c;一个好的远程控制工具都能让我们的工作更加高效。下面&#xff0c;我将分享我对几款流行的远程控制软件的个人体验&#xff0c;并给出我的推荐。 向日葵远程控制 直达链接&#xff1a;down.oray.com 向日葵远程控制是…

如何实现一个基于 HTML+CSS+JS 的任务进度条

如何实现一个基于 HTMLCSSJS 的任务进度条 在网页开发中&#xff0c;任务进度条是一种常见的 UI 组件&#xff0c;它可以直观地展示任务的完成情况。本文将向你展示如何使用 HTML CSS JavaScript 来创建一个简单的、交互式的任务进度条。用户可以通过点击进度条的任意位置来…

Spring Boot读取resources目录下文件(打成jar可用),并放入Guava缓存

1、文件所在位置&#xff1a; 2、需要Guava依赖&#xff1a; <dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>23.0</version></dependency>3、启动时就读取放入缓存的代码&#xf…

10.8作业

优化登录框&#xff1a; 当用户点击取消按钮&#xff0c;弹出问题对话框&#xff0c;询问是否要确定退出登录&#xff0c;并提供两个按钮&#xff0c;yes|No&#xff0c;如果用户点击的Yes&#xff0c;则关闭对话框&#xff0c;如果用户点击的No&#xff0c;则继续登录 当用户点…

26.删除有序数组中的重复项

题目::26. 删除有序数组中的重复项 - 力扣&#xff08;LeetCode&#xff09; 思路:只要不和前面的数一样就可以移动指针&#xff0c;进行赋值 代码: class Solution { public:int removeDuplicates(vector<int>& nums) {int slow 0 ;for(int fast 1; fast < …

Sharding-JDBC笔记04-分库分表实战

文章目录 前言一、需求描述二、数据库设计三、环境说明四、环境准备4.1.mysql主从同步(windows)4.2.初始化数据库 五、实现步骤5.1 搭建maven工程引入maven依赖 5.2 实体类5.3 dao层5.4 服务类5.5 测试类总结 5.6 查询商品DaoService单元测试输出小结 5.7 统计商品Dao单元测试统…

许昌文旅助手:AI智能体在文旅领域的创新应用

哈哈&#xff0c;大家好&#xff0c;我是王帅旭&#xff0c;来自大禹智库&#xff0c;也是《实战AI智能体》一书的作者。今天&#xff0c;咱们就来聊聊一个超级有趣的案例——许昌文旅助手&#xff0c;看看AI智能体是如何在文旅领域大放异彩的&#xff01; 无限拓展的能力集&am…

10.8QTQMessageBox练习

QQ界面 widget.cpp #include "widget.h"Widget::Widget(QWidget *parent): QWidget(parent) {//设置框体的大小和颜色this->setFixedSize(350,500);this->setStyleSheet("background-color:#e5f0ff;");//创建一个LineEdit edit1edit1 new QLineEdi…