Java学数据结构(4)——PriorityQueue(优先队列) 二叉堆(binary heap)

在这里插入图片描述

前言

数据结构与算法作为计算机科学的基础,是一个重点和难点,在实际编程中似乎看不它们的身影,但是它们有随处不在,如影随形。

本系列博客是《数据结构与算法分析—Java语言描述》的读书笔记,合集文章列表如下:

数据结构与算法(Data Structures and Algorithm)——跟着Mark Allen Weiss用Java语言学习数据结构与算法

本篇博客介绍二叉堆(binary heap),它的使用对于PriorityQueue(优先队列)的实现相当普遍,以至于当堆(heap)这个词不加修饰地用在优先队列的上下文中时,一般都是指数据结构的这种实现。

在这里插入图片描述

其他相关的本书的学习笔记博客文章列表如下:

  • Java学数据结构(1)——抽象数据类型ADT & 表List、栈Stack和队列Qeue

  • Java学数据结构(2)——树Tree & 二叉树binary tree & 二叉查找树 & AVL树 & 树的遍历

  • Java学数据结构(3)——树Tree & B树 & 红黑树 & Java标准库中的集合Set与映射Map & 使用多个映射Map的案例

  • Java学数据结构(4)——散列表Hash table & 散列函数 & 哈希冲突

目录

  • 前言
  • 引出
  • 优先队列(堆)
  • 二叉堆
    • 结构性质
    • 堆序性质
  • 堆的基本操作
    • 插入元素 (上滤percolate up)
    • 删除最小元素
  • 总结

引出


1.PriorityQueue(优先队列)是一种特殊的队列数据结构,其中每个元素都有一个优先级;
2.insert(插入)和deleteMin(删除最小者)的方式;

优先队列(堆)

虽然发送到打印机的作业一般被放到队列中,但这未必总是最好的做法。例如,可能有一项作业特别重要,因此希望只要打印机一有空闲就来处理这项作业。反之,若在打印机有空时正好有多个单页的作业及一项100页的作业等待打印,则更合理的做法也许是最后处理长的作业,尽管它不是最后提交上来的(不幸的是,大多数的系统并不这么做,有时可能特别令人懊恼)。

类似地,在多用户环境中,操作系统调度程序必须决定在若干进程中运行哪个进程。一般一个进程只被允许运行一个固定的时间片。一种算法是使用一个队列。开始时作业被放到队列的末尾。调度程序将反复提取队列中的第一个作业并运行它,直到运行完毕,或者该作业的时间片用完,并在作业未运行完毕时把它放到队列的末尾。

这种策略一般并不太合适,因为一些很短的作业由于一味等待运行而要花费很长的时间去处理。一般说来,短的作业要尽可能快地结束,这一点很重要,因此在已经运行的作业当中这些短作业应该拥有优先权。此外,有些作业虽不短小但很重要,也应该拥有优先权。这种特殊的应用似乎需要一类特殊的队列,我们称之为优先队列(priority queue)。

  • 优先队列ADT的有效实现。
  • 优先队列的使用。
  • 优先队列的高级实现

我们将看到的这类数据结构属于计算机科学中最精致的一种

PriorityQueue(优先队列)是一种特殊的队列数据结构,其中每个元素都有一个优先级。在PriorityQueue中,元素按照优先级的顺序进行排序,具有最高优先级的元素最先被取出。

下面是一些PriorityQueue的应用案例:

  1. 任务调度:在一个多任务系统中,每个任务都有不同的优先级。可以使用PriorityQueue来管理任务队列,确保高优先级的任务先被执行。
  2. 事件处理:在事件驱动的系统中,事件可能具有不同的优先级。PriorityQueue可以用于按照优先级处理事件,确保高优先级的事件先被处理。
  3. 路由算法:在网络路由中,路由器需要根据不同的路由策略选择最佳的路径。PriorityQueue可以用于存储和排序路由信息,以便选择最佳路径。
  4. 资源分配:在资源管理系统中,资源可能有不同的优先级和需求。PriorityQueue可以用于按照优先级分配资源,确保高优先级的任务获得足够的资源。
  5. 任务调度器:在操作系统中,任务调度器负责管理和调度进程。PriorityQueue可以用于按照进程的优先级进行调度,确保高优先级的进程先被执行。

这些只是PriorityQueue的一些应用案例,实际上,PriorityQueue在许多领域都有广泛的应用,特别是需要按照优先级进行排序和处理的场景。

在这里插入图片描述

优先队列是允许至少下列两种操作的数据结构:insert(插入),它的作用是显而易见的;以及deleteMin(删除最小者),它的工作是找出、返回并删除优先队列中最小的元素。insert操作等价于enqueue(人队),而deleteMin则是队列运算dequeue(出队)在优先队列中的等价操作。

二叉堆

我们将要使用的这种工具叫作二叉堆(binary heap),它的使用对于优先队列的实现相当普遍,以至于当堆(heap)这个词不加修饰地用在优先队列的上下文中时,一般都是指数据结构的这种实现。在本节,我们把二叉堆只叫作堆。

像二叉查找树一样,堆也有两个性质,即结构性和堆序性。恰似AVL树,对堆的一次操作可能破坏这两个性质中的一个,因此,堆的操作必须到堆的所有性质都被满足时才能终止。事实上这并不难做到。

结构性质

堆是一棵被完全填满的二叉树,有可能的例外是在底层,底层上的元素从左到右填入。这样的树称为完全二叉树(complete binary tree)。图6-2给出了一个例子

在这里插入图片描述

一个重要的观察发现,因为完全二叉树这么有规律,所以它可以用一个数组表示而不需要使用链。图6-3中的数组对应图6-2中的堆。

在这里插入图片描述

数据结构的分析

在这里插入图片描述

堆序性质

让操作快速执行的性质是堆序性质(heap-order property)。由于我们想要快速找出最小元,因此最小元应该在根上。如果我们考虑任意子树也应该是一个堆,那么任意节点就应该小于它的所有后裔。

在这里插入图片描述

根据堆序性质,最小元总可以在根处找到。因此,我们以常数时间得到附加操作findMin

堆的基本操作

插入元素 (上滤percolate up)

为将一个元素X插入到堆中,我们在下一个可用位置创建一个空穴,否则该堆将不是完全树。如果X可以放在该空穴中而并不破坏堆的序,那么插入完成。否则,我们把空穴的父节点上的元素移人该空穴中,这样,空穴就朝着根的方向上冒一步。继续该过程直到X能被放人空穴中为止。

如图6-6所示,为了插入14,我们在堆的下一个可用位置建立一个空穴。由于将14插入空穴破坏了堆序性质,因此将31移入该空穴。在图6-7中继续这种策略,直到找出置入14的正确位置。

这种一般的策略叫作上滤(percolate up);新元素在堆中上滤直到找出正确的位置。

比如如下的一个堆

在这里插入图片描述

插入元素的流程拆解

在这里插入图片描述

全体流程解析

在这里插入图片描述

package com.tianju.security.dataStructure.head;import java.util.Arrays;
import java.util.List;public class BinaryHeap<AnyType extends Comparable<? super AnyType>> {private AnyType[] array;private int size; // 数组中的元素数量private static final int DEFAULT_CAPACITY =10; // 默认容量为10public BinaryHeap() {}public BinaryHeap(AnyType[] array) {this.array = array;this.size = array.length-1;}public Integer size(){return size;}public void insert(AnyType x){System.out.println("扩容之前:"+size);// 如果放不下,就扩容if (array.length+1>array.length){int newLen = array.length + (array.length>>1);array = Arrays.copyOf(array, newLen);System.out.println("扩容之后:"+array.length);}System.out.println(array[size]);array[size+1]=x;printArr();int currLength = size+1;int forTimes = 0;while (currLength/2!=1){System.out.println("循环次数"+forTimes++);if (array[currLength/2].compareTo(x)>0){// 进行上冒AnyType temp = array[currLength/2];System.out.println("当前"+currLength/2+"位置的元素:"+temp);array[currLength/2] = x;array[currLength] = temp;}currLength=currLength/2;}size++;System.out.println("当前长度:"+size);}public void printArr(){System.out.println();System.out.print("[");StringBuilder s = new StringBuilder("[");for(AnyType x:array){
//            System.out.print(x+", ");s.append(x).append(", ");}for (int i=1;i<size;i++){System.out.print(array[i]+", ");}System.out.print("]");System.out.println();s.append("]");System.out.println(s);}}

在这里插入图片描述

package com.tianju.security.dataStructure.head;import java.util.Arrays;
import java.util.List;public class BinaryTestDemo {public static void main(String[] args) {List<Integer> list = Arrays.asList(0,13,21,16,24,31,19,68,65,26,32);Integer[] array = list.toArray(new Integer[list.size()]);BinaryHeap<Integer> binaryHeap = new BinaryHeap<>(array);binaryHeap.printArr();binaryHeap.insert(14);binaryHeap.printArr();System.out.println(binaryHeap.size());}
}

在这里插入图片描述

在这里插入图片描述

上图的Heap堆插入元素2的流程

在这里插入图片描述

删除最小元素

deleteMin以类似于插入的方式处理。找出最小元是容易的,困难之处是删除它。当删除一个最小元时,要在根节点建立一个空穴。由于现在堆少了一个元素,因此堆中最后一个元素X必须移动到该堆的某个地方。如果X可以被放到空穴中,那么deleteMin完成。不过这一般不太可能,因此我们将空穴的两个儿子中较小者移入空穴,这样就把空穴向下推了一层。重复该步骤直到X可以被放入空穴中。因此,我们的做法是将X置入沿着从根开始包含最小儿子的一条路径上的一个正确的位置。

在这里插入图片描述


总结

1.PriorityQueue(优先队列)是一种特殊的队列数据结构,其中每个元素都有一个优先级;
2.insert(插入)和deleteMin(删除最小者)的方式;

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

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

相关文章

【开发日记】Docker搭建Maven私服

文章目录 前言1、拉取镜像2、创建本地目录3、启动容器4、访问5、上传依赖6、项目配置私服 前言 Maven私服是一种特殊的远程仓库&#xff0c;它是架设在局域网内的仓库服务&#xff0c;用来代理位于外部的远程仓库&#xff08;中央仓库、其他远程公共仓库&#xff09;。 在公司…

docker 部署 xxl-job SpringBoot 整合 xxl-job 执行任务

概述 XXL-JOB是一个轻量级的分布式任务调度平台&#xff0c;具有以下特点&#xff1a; 调度模块&#xff1a;负责管理调度信息&#xff0c;发出调度请求&#xff0c;支持可视化和动态的操作&#xff0c;监控调度结果和日志&#xff0c;支持执行器Failover 执行模块&#xff1…

【axmol-2.1 vs cocos2dx性能备忘】

axmol-2.1-08c0605 cocos2d-x-4.0 cocos2d-x-3.17.1 结论 从多边形Sprite渲染性能测试用例看&#xff0c;axmol相对于cocos2d-x-4.0提升42%, 相对于cocos2d-x-3.17.1提升30.8%

mysql面试题35:MySQL有关权限的表有哪些?

该文章专注于面试,面试只要回答关键点即可,不需要对框架有非常深入的回答,如果你想应付面试,是足够了,抓住关键点 面试官:MySQL有关权限的表有哪些? MySQL中与权限相关的表主要包括以下几个: user表:存储MySQL用户的基本信息,包括用户名、密码等。可以使用以下命令…

CPU的执行流程

CPU的执行流程 取指令&#xff08;Instruction Fetch&#xff09;&#xff1a;CPU 从程序存储器&#xff08;通常是内存&#xff09;中获取要执行的下一条指令。这个过程包括以下步骤&#xff1a; CPU 从程序计数器&#xff08;Program Counter&#xff0c;PC&#xff09;中获…

chromium线程模型(1)-普通线程实现(ui和io线程)

通过chromium 官方文档&#xff0c;线程和任务一节我们可以知道 &#xff0c;chromium有两类线程&#xff0c;一类是普通线程&#xff0c;最典型的就是io线程和ui线程。 另一类是 线程池线程。 今天我们先分析普通线程的实现&#xff0c;下一篇文章分析线程池的实现。&#xff…

2023年危险化学品经营单位主要负责人证考试题库及危险化学品经营单位主要负责人试题解析

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2023年危险化学品经营单位主要负责人证考试题库及危险化学品经营单位主要负责人试题解析是安全生产模拟考试一点通结合&#xff08;安监局&#xff09;特种作业人员操作证考试大纲和&#xff08;质检局&#xff09;特…

接口测试及常用接口测试工具

首先&#xff0c;什么是接口呢&#xff1f; 接口一般来说有两种&#xff0c;一种是程序内部的接口&#xff0c;一种是系统对外的接口。 系统对外的接口&#xff1a;比如你要从别的网站或服务器上获取资源或信息&#xff0c;别人肯定不会把数据库共享给你&#xff0c;他只能给你…

dbeaver 插入别名设置禁用

1&#xff0c;前提 最近换了一个数据库连接工具&#xff0c;初次使用&#xff0c;非常别扭。 2&#xff0c;问题 首先遇到的第一个问题是 每次输入from table时&#xff0c;后面就会自动添加一个表别名 tt&#xff0c;然后语句就变成这样 from table tt &#xff0c;所以每次…

四维曲面如何画?matlab

clc; clear all [theta,phi]meshgrid(linspace(0,pi,50),linspace(0,2*pi,50)); zcos(theta); xsin(theta).*cos(phi); ysin(theta).*sin(phi); f-1*((x.*y).2(y.*z).2(z.*x).^2); surf(sin(theta).*cos(phi).*f,sin(theta).*sin(phi).*f,cos(theta).*f,f) 结果

Maven系列第2篇:安装、配置、mvn运行过程详解

maven系列目标&#xff1a;从入门开始开始掌握一个高级开发所需要的maven技能。 这是maven系列第2篇。 本文主要内容 linux中安装maven window中安装maven mvn命令运行的原理 maven配置设置 本篇环境 jdk1.8 maven3.6.2 我们要写java代码&#xff0c;需要安装jdk&…

微信小程序案例:2-2本地生活

文章目录 一、实现步骤&#xff08;一&#xff09;创建项目&#xff08;二&#xff09;创建页面&#xff08;三&#xff09;准备图片素材&#xff08;四&#xff09;编写页面结构1、编写轮播区域页面结构2、编写九宫格区域页面结构 &#xff08;五&#xff09;编写页面样式1、编…

【PPT制作】基础篇

文章目录 一、PPT制作必要的基础设置1.1 自动保存1.2 字体嵌入1.3 撤销步数1.4 图像大小和质量 二、必备快捷键三、设计四原则四、总结 ヾ(๑╹◡╹)&#xff89;" 没有坚持的努力&#xff0c;本质上并没有多大意义ヾ(๑╹◡╹)&#xff89;" 一、PPT制作必要的基础…

MinIO的安装与使用

文章目录 1.MINIO是什么&#xff1f;2.MINIO安装3.启动脚本4.打开MINIO页面5.MC命令6.MINIO备份脚本 1.MINIO是什么&#xff1f; MinIO 是一款高性能、分布式的对象存储系统. 它是一款软件产品, 可以100%的运行在标准硬件。即X86等低成本机器也能够很好的运行MinIO。 MinIO与…

Python 人工智能 Machine Learning 机器学习基础知识点详细教程(更新中)

人工智能基本介绍 人工智能&#xff08;Artificial Intelligence&#xff0c;AI&#xff09;是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门新的技术科学。它试图了解智能的实质&#xff0c;并生产出一种新的能以人类智能相似的方式做出反应的智…

c++视觉--通道分离,合并处理,在分离的通道中的ROI感兴趣区域里添加logo图片

c视觉–通道分离&#xff0c;合并处理 通道分离: split()函数 #include <opencv2/opencv.hpp>int main() {// 读取图像cv::Mat image cv::imread("1.jpg");// 检查图像是否成功加载if (image.empty()) {std::cerr << "Error: Could not read the…

为什么选择虚拟展会展览?了解虚拟展会展览的应用领域

引言&#xff1a; 相较于传统的实体展览&#xff0c;虚拟展会展览具有吸引力和便捷性&#xff0c;能够在全球范围内进行宣传活动。这种创新形式不仅能够降低成本、扩大受众范围&#xff0c;还能够提供没有过的互动性和数据分析。 一&#xff0e;虚拟展会展览简介 虚拟展会展览…

Laya3.0 入门教程

点击play箭头 点击右边的开发者工具 就会弹出 chrome的调试窗口 然后定位到你自己的ts文件 直接在ts里断点即可 不需要js文件 如何自动生成代码&#xff1f; 比如你打开一个新项目 里面显示的是当前场景 只需要点击 UI运行时 右边的框就可以了 他会自动弹窗提示你 创建一个文…

虹科分享 | 确保冻干工艺开发中精确测量和数据完整性的5步指南

虹科分享 | 确保冻干工艺开发中精确测量和数据完整性的5步指南 介绍 冻干周期的工艺开发在冻干中起着至关重要的作用&#xff0c;因为它可以优化关键工艺参数&#xff0c;以实现理想的产品质量和工艺一致性。优化冻干工艺还可以缩短运行时间&#xff0c;尽早发现关键错误&…

Practical Memory Leak Detection using Guarded Value-Flow Analysis 论文阅读

本文于 2007 年投稿于 ACM-SIGPLAN 会议1。 概述 指针在代码编写过程中可能出现以下两种问题&#xff1a; 存在一条执行路径&#xff0c;指针未成功释放&#xff08;内存泄漏&#xff09;&#xff0c;如下面代码中注释部分所表明的&#xff1a; int foo() {int *p malloc(4 …