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

文章目录

  • 一、优先级队列的概念
  • 二、优先级队列的模拟实现
    • 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.hqwc.cn/news/504446.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2024理解这几个安全漏洞,你也能做安全测试!

如今安全问题显得越来越重要&#xff0c;一个大型的互联网站点&#xff0c;你如果每天查看日志&#xff0c;会发现有很多尝试攻击性的脚本。 如果没有&#xff0c;证明网站影响力还不够大。信息一体化的背后深藏着各类安全隐患&#xff0c;例如由于开发人员的不严谨导致为Web应…

Java虚拟机(JVM)从入门到实战【上】

Java虚拟机&#xff08;JVM&#xff09;从入门到实战【上】&#xff0c;涵盖类加载&#xff0c;双亲委派机制&#xff0c;垃圾回收器及算法等知识点&#xff0c;全系列6万字。 一、基础篇 P1 Java虚拟机导学课程 P2 初识JVM 什么是JVM Java Virtual Machine 是Java虚拟机。…

频率域采样

1. 频率域采样 (1) 采样的过程&#xff1a;DFT的X(k)是对周期且连续的频谱X()在[0,2pi)上的等间隔采样&#xff0c;采N个点得到的&#xff0c;采样间隔是&#xff1b;频域采样要求时域有限&#xff0c;即假设x(n)的长度是有限值M&#xff0c;x(n)的SFT是X()。 (2) X(k) 做IDF…

live555源码学习(1)

1 基础组件 live项目主要包含了四个基础库、程序入口类&#xff08;mediaServer&#xff09;和测试程序&#xff08;testProgs&#xff09;。四个基础库是UsageEnvironment、BasicUsageEnvironment、groupsock和liveMedia UsageEnvironment 抽象了两个类UsageEnvironment和T…

蓝桥杯备战刷题two(自用)

1.杨辉三角形 #include<iostream> using namespace std; #define ll long long const int N2e510; int a[N]; //1 0 0 0 0 0 0 //1 1 0 0 0 0 0 //1 2 1 0 0 0 0 //1 3 3 1 0 0 0 //1 4 6 4 1 0 0 //1 5 10 10 5 1 //前缀和思想 //第一列全为1,第二列为从0开始递增1的序…

整数和浮点数在内存中的存储(大小端字节序,浮点数的存取)

目录 1.整数在内存中的存储 2.大小端字节序和字节序判断 2.1什么是大小端&#xff1f; 2.2为什么会有大小端 3.浮点数在内存中的存储 3.1浮点数的存储 3.1.1 浮点数存的过程 3.1.2 浮点数取的过程 3.2 解析 3.3 验证浮点数的存储方式 1.整数在内存中的存储 整数的二进…

前端工程化(黑马学习笔记)

前端工程化介绍 我们目前的前端开发中&#xff0c;当我们需要使用一些资源时&#xff0c;例如&#xff1a;vue.js&#xff0c;和axios.js文件&#xff0c;都是直接再工程中导入的&#xff0c;如下图所示&#xff1a; 但是上述开发模式存在如下问题&#xff1a; ● 每次开发都是…

程序项目打包发布方法,采用InstallShield软件

重点&#xff1a; 1.程序项目做出来了&#xff0c;需要打包发布给用户。如何打包是关键。 2.采用InstallShield软件进行发布。 步骤一&#xff1a;创建一个依赖三方库配置环境的bat文件的项目。 &#xff08;主要测试三方库打包 和如果有bat文件&#xff0c;需要先创建环境&…

等概率事件算法

1等概率的生成(0-8)范围内的正整数 // Math.random 数据范围[0,1) 且 是 等概率的产生随机数 // 应用&#xff1a; // 1.生成等概率的整数&#xff08;等概率的生成(0-8)范围内的正整数 int value (int) (Math.random() * 9); System.out.println("value "…

Three 基础环境 实例(总结一)

Three 基础环境 THREE三要素 &#xff08;scene场景、camera摄像机、renderer渲染器&#xff09; 1、首先我们需要引入three.js包&#xff0c;引入 three.js 对象&#xff08;命名导出->默认导入&#xff09; import * as THREE from three; 2、创建scene场景 const s…

(C语言)函数详解上

&#xff08;C语言&#xff09;函数详解上 目录&#xff1a; 1. 函数的概念 2. 库函数 2.1 标准库和头文件 2.2 库函数的使用方法 2.2.1 sqrt 功能 2.2.2 头文件包含 2.2.3 实践 2.2.4 库函数文档的一般格式 3. 自定义函数 3.1 函数的语法形式 3.2 函数的举例 4. 形参和实参 4.…

手势识别应用介绍

目录 一、功能介绍 二、安装部署说明 2.1 文件目录说明 2.2 手势识别部分 一、功能介绍 这是一个通过摄像头捕获手势&#xff0c;根据不同的手势来做出不同操作的计算机程序。目前可以识别9种手势&#xff0c;可以根据识别到的手势&#xff0c;进行打开应用、增大音量、减小音量…