数据结构第27节 优先队列

优先队列(Priority Queue)是在计算机科学中一种非常有用的抽象数据类型,它与标准队列的主要区别在于元素的出队顺序不是先进先出(FIFO),而是基于每个元素的优先级。具有较高优先级的元素会比低优先级的元素更早出队。在Java中,PriorityQueue类是实现优先队列的一种方式。

Java中的PriorityQueue

java.util.PriorityQueue是Java集合框架的一部分,它实现了Queue接口。PriorityQueue底层使用了一个名为堆的数据结构,通常是一个二叉堆,以保证每次操作的时间复杂度为O(log n),其中n是队列中的元素数量。

主要特点:
  1. 元素排序PriorityQueue默认按照自然排序(自然顺序)来排序元素,即元素必须实现Comparable接口,或者在创建PriorityQueue时提供一个Comparator对象来定制排序规则。

  2. 最小堆行为PriorityQueue默认表现得像一个最小堆,即队列的头部元素是最小的元素。如果需要最大堆的行为,可以通过自定义比较器来实现。

  3. 不允许null元素PriorityQueue不允许插入null元素。

  4. 不支持随机访问PriorityQueue不支持快速随机访问元素,因为它不是基于索引的结构。

常用方法:
  • add(E e):将指定的元素添加到此队列中。
  • offer(E e):如果可能立即添加指定的元素而不会违反队列的容量限制,则添加;否则返回false。
  • remove():检索并移除此队列的头;如果此队列为空,则抛出NoSuchElementException异常。
  • poll():检索并移除此队列的头;如果此队列为空,则返回null。
  • peek():检索但不移除此队列的头;如果此队列为空,则返回null。
  • size():返回队列中的元素个数。
  • isEmpty():如果队列中没有元素,则返回true。
示例代码:

下面是一个使用PriorityQueue的例子,展示如何创建和使用一个优先队列:

import java.util.PriorityQueue;
import java.util.Comparator;public class PriorityQueueExample {public static void main(String[] args) {// 创建一个基于数字大小的优先队列PriorityQueue<Integer> pq = new PriorityQueue<>();// 添加元素pq.add(5);pq.add(1);pq.add(3);// 输出队列头部的元素System.out.println("Head element: " + pq.peek()); // 输出最小的元素,这里是1// 移除并输出队列头部的元素System.out.println("Removed head element: " + pq.remove()); // 输出并移除最小的元素,这里是1// 使用自定义比较器创建优先队列PriorityQueue<String> pqStrings = new PriorityQueue<>(new Comparator<String>() {@Overridepublic int compare(String s1, String s2) {return s2.compareTo(s1); // 反转字符串的排序顺序}});// 添加字符串元素pqStrings.add("Apple");pqStrings.add("Banana");pqStrings.add("Cherry");// 输出队列头部的元素System.out.println("Head element: " + pqStrings.peek()); // 输出最大的元素,这里是"Cherry"}
}

在这个例子中,我们创建了两个PriorityQueue实例。第一个实例是基于整数的优先队列,按照数字大小排序。第二个实例是基于字符串的优先队列,使用自定义的比较器来反转字符串的自然排序顺序。

优先队列在很多场景下都非常有用,比如任务调度、事件驱动模拟、Dijkstra算法中的最短路径计算、以及各种基于优先级的系统中。

下面我会给出几个具体的场景以及相应的Java代码实现,以便你了解优先队列在实际编程中的应用方式。

场景1:任务调度

在任务调度场景中,优先级高的任务会被优先执行。这里我们使用PriorityQueue来管理任务列表。

import java.util.PriorityQueue;class Task implements Comparable<Task> {private String name;private int priority;public Task(String name, int priority) {this.name = name;this.priority = priority;}public String getName() {return name;}public int getPriority() {return priority;}@Overridepublic int compareTo(Task other) {return Integer.compare(this.priority, other.priority);}
}public class TaskScheduler {private PriorityQueue<Task> tasks = new PriorityQueue<>();public void addTask(Task task) {tasks.add(task);}public Task getNextTask() {return tasks.poll();}public static void main(String[] args) {TaskScheduler scheduler = new TaskScheduler();scheduler.addTask(new Task("Task1", 3));scheduler.addTask(new Task("Task2", 1));scheduler.addTask(new Task("Task3", 2));while (!scheduler.tasks.isEmpty()) {Task task = scheduler.getNextTask();System.out.println("Executing: " + task.getName());}}
}

场景2:Dijkstra算法

Dijkstra算法用于在加权图中寻找两个顶点之间的最短路径。优先队列在这里用来保存待访问的顶点,按照它们的当前最小距离排序。

import java.util.*;public class DijkstraAlgorithm {private Map<String, List<Edge>> graph = new HashMap<>();private Map<String, Integer> distances = new HashMap<>();private PriorityQueue<Edge> queue = new PriorityQueue<>();public void addEdge(String source, String destination, int weight) {graph.computeIfAbsent(source, k -> new ArrayList<>()).add(new Edge(destination, weight));}public void calculateShortestPaths(String startVertex) {distances.put(startVertex, 0);queue.add(new Edge(startVertex, 0));while (!queue.isEmpty()) {Edge edge = queue.poll();String vertex = edge.getDestination();if (distances.containsKey(vertex)) continue; // Already processeddistances.put(vertex, edge.getWeight());for (Edge neighbor : graph.getOrDefault(vertex, Collections.emptyList())) {queue.add(new Edge(neighbor.getDestination(), distances.get(vertex) + neighbor.getWeight()));}}}public static void main(String[] args) {DijkstraAlgorithm dijkstra = new DijkstraAlgorithm();dijkstra.addEdge("A", "B", 5);dijkstra.addEdge("A", "C", 10);dijkstra.addEdge("B", "D", 3);dijkstra.addEdge("C", "D", 1);dijkstra.addEdge("C", "E", 2);dijkstra.addEdge("D", "E", 1);dijkstra.addEdge("D", "F", 5);dijkstra.addEdge("E", "F", 5);dijkstra.calculateShortestPaths("A");System.out.println(dijkstra.distances);}static class Edge implements Comparable<Edge> {private String destination;private int weight;public Edge(String destination, int weight) {this.destination = destination;this.weight = weight;}public String getDestination() {return destination;}public int getWeight() {return weight;}@Overridepublic int compareTo(Edge other) {return Integer.compare(this.weight, other.weight);}}
}

场景3:事件驱动的模拟

在事件驱动的模拟中,事件按照发生的时间排序。优先队列可以用来保持事件列表的有序性。

import java.util.PriorityQueue;class Event implements Comparable<Event> {private long time;private String description;public Event(long time, String description) {this.time = time;this.description = description;}public long getTime() {return time;}public String getDescription() {return description;}@Overridepublic int compareTo(Event other) {return Long.compare(this.time, other.time);}
}public class EventDrivenSimulation {private PriorityQueue<Event> events = new PriorityQueue<>();public void scheduleEvent(long time, String description) {events.add(new Event(time, description));}public void runSimulation() {while (!events.isEmpty()) {Event event = events.poll();System.out.println("Time: " + event.getTime() + ", Event: " + event.getDescription());}}public static void main(String[] args) {EventDrivenSimulation simulation = new EventDrivenSimulation();simulation.scheduleEvent(1000, "Start");simulation.scheduleEvent(1010, "Event 1");simulation.scheduleEvent(1005, "Event 2");simulation.runSimulation();}
}

在上述代码中,我们创建了三个不同的场景,每个场景都展示了PriorityQueue在不同应用场景下的使用方式。希望这些示例能够帮助你更好地理解优先队列在实际编程中的作用。

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

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

相关文章

论文写作经验-摘要1

小王搬运工 时序课堂 2024年07月15日 13:10 新疆 本人菜鸡一名&#xff0c;最近几篇论文实验跑的比较顺利&#xff0c;结果也很不错&#xff0c;奈何于自己写作能力巨差&#xff0c;导致文章屡屡被拒。当前正在跟一位非常牛的老师学习写作技巧&#xff0c;我将一些心得体会和技…

MySQL教程 | 笔记 (包含数据库、表设计,数据库的增删改查操作;数据库优化等知识点)

SQL简介 一门操作关系型数据库的编程语言&#xff0c;定义操作所有关系型数据库的统一标准 通用语法&#xff1a; 可以单行或者多行书写&#xff0c;以分号结尾&#xff1b; 可以使用空格 / SQL语句可以使用空格/缩进来增强语句的可读性。 MySQL数据库的SOL语句不区分大小…

Flink Window 窗口【更新中】

Flink Window 窗口 在Flink流式计算中&#xff0c;最重要的转换就是窗口转换Window&#xff0c;在DataStream转换图中&#xff0c;可以发现处处都可以对DataStream进行窗口Window计算。 窗口&#xff08;window&#xff09;就是从 Streaming 到 Batch 的一个桥梁。窗口将无界流…

C#+GDAL影像处理笔记09:创建多边形、多部件图形、合并相邻的多边形

使用GDAL创建多边形、多部件要素、相邻面合并、以及shape文件创建的完整过程 1. 创建一个多边形 多边形必须闭合 // 创建第一个多边形几何对象Geometry polygon1 = new Geometry(wkbGeometryType.wkbPolygon);Geometry ring1 = new Geometry(wkbGeometryType.wkbLinearRing);…

银河麒麟如何部署QtMqtt(入门案例教程)

QtMqtt是一个基于Qt的MQTT客户端库,提供了使用MQTT协议与 MQTT broker 进行通信的功能。silver-linix是一个基于Linux的操作系统,用于嵌入式系统和物联网设备。下面将教您如何在silver-linix上部署QtMqtt。 1. 安装QtMqtt 1.1 安装QtMqtt依赖项 QtMqtt依赖于Qt和QtNetwork…

跨越空间的编码:在PyCharm中高效使用远程解释器

跨越空间的编码&#xff1a;在PyCharm中高效使用远程解释器 PyCharm的强大功能之一是支持远程解释器&#xff0c;这使得开发者能够在远程服务器或虚拟机上运行、调试代码&#xff0c;享受本地开发环境的便利。本文将详细介绍如何在PyCharm中配置和使用远程解释器&#xff0c;包…

系统架构师考点--软件工程(上)

大家好。今天我来总结一下软件工程的相关考点。这部分是考试的重点。在上午场客观题、下午场案例题以及下午场论文都有可能考到&#xff0c;在上午场客观题中大约占12-15分左右。 一、软件工程概述 软件开发生命周期 软件定义时期&#xff1a;包括可行性研究和详细需求分析过…

构建革新:在Gradle中打造自定义插件的终极指南

构建革新&#xff1a;在Gradle中打造自定义插件的终极指南 在构建自动化的征途上&#xff0c;Gradle以其灵活性和强大的扩展能力成为开发者的得力助手。自定义插件是Gradle生态中的一颗璀璨明珠&#xff0c;它允许开发者根据特定需求扩展Gradle的功能。本文将带你走进Gradle自…

uniapp打包成Android时,使用uni.chooseLocation在App端显示的地址列表是空白?一直转圈的解决办法

问题描述&#xff1a; uniapp打包后的测试版app在ios里可以显示高德地图的定位列表&#xff0c;但是安卓手机却不显示定位列表&#xff0c;一直在转圈圈&#xff0c;怎么回事&#xff1f;之前的功能在正式版都能用&#xff0c;真机运行也能用&#xff0c;为什么测试版的安卓手…

ADC性能规格--动态性能

所有真正的ADC都有额外的噪声源和失真过程&#xff0c;会降低性能。 动态性能规范报告了ADC动态行为中的这些缺陷&#xff0c;包括总谐波失真&#xff08;THD&#xff09;、信噪比加失真&#xff08;SND&#xff09;、信号噪声比&#xff08;SNR&#xff09;和无杂散动态范围&a…

【MySQL】7.MySQL 的内置函数

MySQL的内置函数 一.日期函数二.字符串函数三.数学函数四.其它函数 一.日期函数 函数名称说明current_date()当前日期current_time()当前时间current_timestamp当前时间戳(日期时间)date(datetime)截取 datetime 的日期部分date_add(date, interval d_value_type)给 date 添加…

Study--Oracle-07-ASM自动存储管理(二)

一、ASM安装准备条件 1、ASM支持存储类型 本地祼设备(本地的磁盘和分区) 网络附加存储(NAS) 存储区域网络(SAN) 2、ASM使用本地裸设备,要点: 已经被挂载到操作系统上或者已经做了分区 映射裸设备为文件名 设置正确的权限(针对grid用户和asmadmin组,权限为660) 二、OR…

ABAP面试题收集

面试阶段 第一阶段&#xff1a;自我介绍&#xff0c;简单介绍简况&#xff0c;尽量不要喋喋不休 第二阶段&#xff1a;根据简历问技术&#xff0c;不会的东西不要在简历上硬写 第三阶段&#xff1a;技术面 一般来说会有&#xff1a; 做过哪些增强&#xff08;隐式&#xff0c;出…

【CUDA】CUDA中缓存机制对计时的影响

笔者在阅读知乎上一个关于CUDA编程的专栏时&#xff0c;发现作者写的很多文章中都会附带计时的模块用于评估程序的运行效率&#xff0c;然而笔者发现&#xff0c;在运行这篇文章中的代码时时&#xff0c;得到的结果和作者的结果有较大差异&#xff0c;主要体现在&#xff1a;使…

React一基础

代码下载 React 概述 React 是一个用于构建用户界面的javaScript库&#xff0c;起源于facebook的内部项目&#xff0c;后续在13年开源了出来。 特点&#xff1a; 声明式——只需要描述UI看起来是什么样式&#xff0c;就跟写HTML一样&#xff0c;React负责渲染UI基于组件——…

Python - Word转TXT文本,或TXT文本转Word

Word文档&#xff08;.doc或.docx&#xff09;和纯文本文件&#xff08;.txt&#xff09;是两种常用的文件格式。Word文档通常用于复杂的文档处理和排版&#xff0c;而纯文本文件则用于存储和传输纯文本信息。了解如何在这两种格式之间进行转换能提高工作效率&#xff0c;并便于…

Pytorch使用Dataset加载数据

1、前言&#xff1a; 在阅读之前&#xff0c;需要配置好对应pytorch版本。 对于一般学习&#xff0c;使用cpu版本的即可。参考教程点我 导入pytorch包&#xff0c;使用如下命令即可。 import torch # 注意虽然叫pytorch&#xff0c;但是在引用时是引用torch2、神经网络获取…

【UE5.3】笔记11

一、变量的SET&&GET 1、创建变量保存数据&#xff0c;如下图&#xff0c;找到左侧我的蓝图下的变量&#xff0c;新增一个&#xff0c;并选择类型。使用的时候直接将变量拖到蓝图中&#xff0c;此时会显示两个选项一个是获取一个是设置。 选择获取就是个GET蓝图&#x…

2024文件加密软件有哪些丨超好用的文件加密软件排行榜

文件加密软件在现代数字生活中扮演着至关重要的角色&#xff0c;尤其是在保护个人隐私、商业机密和敏感数据方面。 加密软件可以防止未经授权的访问和数据泄露。即使设备丢失或被盗&#xff0c;加密后的文件也不会轻易被破解&#xff0c;从而保护了数据的安全。 对于企业而言…

Bootstrap 辅助类

Bootstrap 辅助类 Bootstrap 是一个流行的前端框架&#xff0c;它提供了一套丰富的辅助类&#xff0c;这些辅助类可以帮助开发者快速实现各种布局和样式效果。辅助类是 Bootstrap 中的一个重要组成部分&#xff0c;它们提供了一种简洁、直观的方式来控制元素的显示和隐藏、浮动…