【算法基础实验】排序-最小优先队列MinPQ

news2024/11/25 18:48:30

优先队列

理论知识

MinPQ(最小优先队列)是一种常见的数据结构,用于有效管理一组元素,其中最小元素可以快速被检索和删除。这种数据结构广泛应用于各种算法中,包括图算法(如 Dijkstra 的最短路径算法和 Prim 的最小生成树算法)、事件驱动的模拟、调度任务等。

MinPQ 的核心操作

MinPQ 主要支持以下几种操作:

  1. 插入(Insert) - 将一个新元素添加到优先队列中。
  2. 查找最小(Find Minimum) - 获取优先队列中的最小元素,但不从队列中删除它。
  3. 删除最小(Delete Minimum) - 移除并返回优先队列中的最小元素。
  4. 判断是否为空(IsEmpty) - 检查优先队列是否为空。
  5. 大小(Size) - 返回优先队列中的元素数量。

MinPQ 的实现方式

MinPQ 可以用多种方式实现,其中最常见的是使用二叉堆(Binary Heap)结构,特别是最小堆。最小堆是一个完全二叉树,可以用数组来有效表示,具有以下性质:

  • 每个节点的值都小于或等于其子节点的值。
  • 树是完全填满的,除了最底层,最底层从左向右填充,直到填满。

使用最小堆的优势

使用最小堆实现 MinPQ 的优势在于其操作的高效性:

  • 插入操作删除最小操作的时间复杂度为 O(log n),其中 n 是队列中的元素数量。
  • 查找最小操作的时间复杂度为 O(1),因为最小元素总是位于堆的根部。

应用示例

在许多实时系统和性能要求高的环境中,MinPQ 用来保证重要任务优先处理,或确保数据的最小值可以迅速访问。例如,在网络路由算法中,需要快速找到最短的未处理路径;在模拟环境中,优先处理最早发生的事件。

总的来说,MinPQ 是一种非常实用的数据结构,通过最小堆实现可以提供高效的性能,适用于需要快速访问和删除最小元素的各种应用场景。

在这里插入图片描述

实验数据

tinyPQ.txt测试数据内容

P Q E - X A M - P L E -

算法流程

在这里插入图片描述

代码实现

import edu.princeton.cs.algs4.StdIn;
import edu.princeton.cs.algs4.StdOut;

public class myMinPQ<Key extends Comparable<Key>> {
    private Key[] pq;
    private int n = 0;
    public myMinPQ(int initN){
        pq = (Key[]) new Comparable[initN+1];
    }
    public myMinPQ(){
        this(1);
    }
    public myMinPQ(Key[] keys){
        n = keys.length;
        pq = (Key[]) new Comparable[n+1];

    }
    private void resize(int capacity) {
        Key[] temp = (Key[]) new Comparable[capacity];
        for (int i = 1; i <= n; i++) {
            temp[i] = pq[i];
        }
        pq = temp;
    }
    public boolean isEmpty(){return n == 0;}

    public int size(){return n;}

    public void insert(Key v){
        pq[++n] = v;
        if (n == pq.length - 1) resize(2 * pq.length);
        swim(n);
    }
    public Key delMin(){
        Key min = pq[1];
        exch(1,n--);
        pq[n+1] = null;
        sink(1);
        if ((n > 0) && (n == (pq.length - 1) / 4)) resize(pq.length / 2);
        return min;
    }
    private boolean greater(int i, int j){
        return pq[i].compareTo(pq[j]) > 0;
    }
    private void exch(int i, int j){
        Key t = pq[i]; pq[i]=pq[j]; pq[j]=t;
    }
    private void swim(int k){
        while(k>1 && greater(k/2, k)) {
            exch(k/2,k);
            k=k/2;
        }
    }
    private void sink(int k){
        while(2*k <= n){
            int j = 2*k;
            if(j < n && greater(j, j+1)) j++;
            if(!greater(k,j)) break;
            exch(k,j);
            k = j;
        }
    }

    public static void main(String[] args) {
        myMinPQ<String> pq = new myMinPQ<String>();
        while (!StdIn.isEmpty()) {
            String item = StdIn.readString();
            if (!item.equals("-")) pq.insert(item);
            else if (!pq.isEmpty()) StdOut.print(pq.delMin() + " ");
        }
        StdOut.println("(" + pq.size() + " left on pq)");
    }
}

代码讲解

这段 Java 代码定义了一个名为 myMinPQ 的类,实现了一个最小优先队列(Min Priority Queue)。这个优先队列使用最小堆来维护元素的顺序,以确保能够快速地插入新元素并删除最小元素。下面是对这段代码各部分的详细解释:

类定义和泛型

  • myMinPQ<Key extends Comparable<Key>>: 类定义使用泛型 Key,这意味着队列中的元素必须实现 Comparable 接口,使得元素之间可以比较大小。

字段

  • private Key[] pq;: 存储堆元素的数组。数组从索引1开始使用,以简化父节点和子节点的索引计算。
  • private int n = 0;: 表示堆中元素的数量。

构造函数

  • myMinPQ(int initN): 接受一个初始容量 initN 并创建一个容量为 initN + 1 的数组。
  • myMinPQ(): 无参构造函数,默认初始化容量为1。
  • myMinPQ(Key[] keys): 接受一个数组 keys 并用其初始化优先队列。

方法

  • resize(int capacity): 当数组容量不足以存储更多元素时,调用此方法以调整数组大小。
  • isEmpty(): 检查优先队列是否为空。
  • size(): 返回队列中的元素数量。
  • insert(Key v): 向优先队列中插入一个新元素。使用 swim 方法确保最小堆的属性。
  • delMin(): 从队列中删除并返回最小元素。使用 sink 方法调整堆以维持最小堆的属性。
  • greater(int i, int j): 比较堆中索引 ij 的元素大小。
  • exch(int i, int j): 交换堆中索引 ij 的元素。
  • swim(int k): 上浮操作,调整元素位置以维持堆的顺序。
  • sink(int k): 下沉操作,调整元素位置以维持堆的顺序。

主函数

  • main(String[] args): 主函数从标准输入读取字符串,插入到优先队列中。如果读取到的字符串是 "-" 并且队列不为空,则删除并打印最小元素。最终打印队列中剩余元素的数量。

这个类的实现利用了二叉堆的特性,确保每次插入和删除操作的时间复杂度为 O(log n),从而使得操作效率较高。通过调整数组大小的方式,该实现还可以动态地调整内存使用,以适应不同的使用场景。

实验

代码编译

$ javac myMinPQ.java

代码运行

$ java myMinPQ < data\tinyPQ.txt
E A E (6 left on pq)

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

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

相关文章

弱监督语义分割-对CAM的生成过程进行改进1

一、仿射变换图像结合正则项优化CAM生成 论文&#xff1a;Self-supervised Equivariant Attention Mechanism for Weakly Supervised Semantic Segmentation &#xff08;CVPR,2020&#xff09; 1.SEAM方法 孪生网络架构&#xff08;Siamese Network Architecture&#xff09…

基于Springboot+Vue的Java项目-车辆管理系统开发实战(附演示视频+源码+LW)

大家好&#xff01;我是程序员一帆&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &am…

html划过盒子出现弹窗

<template><div><div class"content">盒子<div class"topUserInfo">弹窗</div></div></div> </template><script> export default {} </script><style lang"less" scoped> .…

Pycharm 执行pytest时,会遇见某些case Empty suite

我这边的情况是有些case就是执行不了&#xff0c;百度了很多&#xff0c;有说设置选pytest的&#xff0c;有命名规范的&#xff0c;都没有成功。后面问了同事之后才发现&#xff0c;pytest 的框架&#xff0c;pytest.ini 执行的时候&#xff0c;加了个标签&#xff0c;主动把某…

2024数维杯B题详细思路代码数学建模高质量保姆级

2024年第九届数维杯大学生数学建模挑战赛题目 B 题 生物质和煤共热解问题的研究 &#xff08;1&#xff09;基于附件一&#xff0c;请分析正己烷不溶物(INS)对热解产率&#xff08;主要 考虑焦油产率、水产率、焦渣产率&#xff09;是否产生显著影响&#xff1f;并利用图像 加…

Spring如何控制Bean的加载顺序

前言 正常情况下&#xff0c;Spring 容器加载 Bean 的顺序是不确定的&#xff0c;那么我们如果需要按顺序加载 Bean 时应如何操作&#xff1f;本文将详细讲述我们如何才能控制 Bean 的加载顺序。 场景 我创建了 4 个 Class 文件&#xff0c;分别命名为 FirstInitialization Se…

2024年文化交流与综合艺术国际学术会议(ICCECA 2024)

2024年文化交流与综合艺术国际学术会议(ICCECA 2024) 2024 International Conference on Cultural Exchange and Comprehensive Art 一、【会议简介】 22024年文化交流与综合艺术国际学术会议&#xff0c;将汇集全球的艺术家和学者。 在这个盛大的学术会议上&#xff0c;来自世…

SQLServer数据库还原重命名

将备份的数据还原&#xff0c;因为数据库名冲突&#xff0c;需要将还原的数据库重命名 1.新建数据库&#xff0c;例如Test1 2.右键数据库-》任务-》还原&#xff0c;进入还原数据库界面 选择设备&#xff0c;然后找到还原数据库备份文件 3.点击文件选项&#xff0c;选中‘将所…

论文阅读:《Sequence can Secretly Tell You What to Discard》,减少推理阶段的 kv cache

目前各类大模型都支持长文本&#xff0c;例如 kimi chat 以及 gemini pro&#xff0c;都支持 100K 以及更高的上下文长度。但越长的上下文&#xff0c;在推理过程中需要存储的 kv cache 也越多。假设&#xff0c;数据的批次用 b 表示&#xff0c;输入序列的长度仍然用 s 表示&a…

Python专题:六、循环语句(1)

补充知识 代码的注释 #描述性文字 阅读代码的人更好的理解代码 while循环语句 x<100条件控制语句&#xff0c;Totalx,Total自增加x&#xff0c;x1&#xff0c;x自增加1&#xff0c;x<100此条件满足时&#xff0c;执行while循环&#xff0c;当x101时&#xff0c;x101条…

开源教程「动手学大模型应用开发」,从零基础到掌握大模型开发的关键技能!

LLM 正逐步成为信息世界的新革命力量&#xff0c;其通过强大的自然语言理解、自然语言生成能力&#xff0c;为开发者提供了新的、更强大的应用开发选择。随着国内外井喷式的 LLM API 服务开放&#xff0c;如何基于 LLM API 快速、便捷地开发具备更强能力、集成 LLM 的应用&…

JAVA文件的简单操作

文件IO&#xff08;Input和Output&#xff09; 文件的输入和输出是人为规定的&#xff0c;那么什么是输入&#xff1f;什么是输出捏&#xff1f;在这里统一已CPU为基准 例如&#xff1a;将文件由内存写入硬盘就是输出&#xff0c;有硬盘写入内存就是输入。可以总结为&#xff…

Mybatis-Plus常用的增删改查坑

添加依赖 <!--实体类上加上Data注解就不用写get&#xff0c;set&#xff0c;toString&#xff0c;equals等方法了--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional…

机器学习算法应用——K近邻分类器(KNN)

K近邻分类器&#xff08;KNN&#xff09;&#xff08;4-2&#xff09; K近邻分类器&#xff08;K-Nearest Neighbor&#xff0c;简称KNN&#xff09;是一种基本的机器学习分类算法。它的工作原理是&#xff1a;在特征空间中&#xff0c;如果一个样本在特征空间中的K个最相邻的样…

docker端口映射成功,docker端口不生效的问题解决,外界无法访问docker映射端口

docker端口映射不生效的问题解决 问题 使用docker run -p 88848:8848后&#xff0c;显示容器启动正常&#xff0c;并且使用docker logs –f xxx能够看到容器可以正常启用&#xff0c;docker ps 可以看到容器启动成功&#xff0c;并且端口已经映射,但是在浏览器访问相关地址&am…

05_SpringCloud

文章目录 SpringCloud服务调用的负载均衡Ribbon负载均衡 面向接口的服务调用OpenFeign 客户端FeignClient日志输出服务调用的超时设置 配置中心Nacos配置中心Nacos配置中心的使用Nacos配置的持久化 SpringCloud 服务调用的负载均衡 问题引出 // 服务发现List<ServiceInstan…

第十二届蓝桥杯省赛真题 Java C 组【原卷】

文章目录 发现宝藏【考生须知】试题 A: ASC试题 B: 空间试题 C: 卡片试题 D: 相乘试题 E: 路径试题 F: 时间显示试题 G: 最少砝码试题 H : \mathrm{H}: H: 杨辉三角形试题 I: 左孩子右兄弟试题 J : \mathrm{J}: J: 双向排序 发现宝藏 前些天发现了一个巨牛的人工智能学习网站…

【SpringBoot篇】基于Redis分布式锁的 误删问题 和 原子性问题

文章目录 &#x1f354;Redis的分布式锁&#x1f6f8;误删问题&#x1f388;解决方法&#x1f50e;代码实现 &#x1f6f8;原子性问题&#x1f339;Lua脚本 ⭐利用Java代码调用Lua脚本改造分布式锁&#x1f50e;代码实现 &#x1f354;Redis的分布式锁 Redis的分布式锁是通过利…

傻傻分不清楚:JDK/JRE/JVM的区别和联系

在Java开发的世界里&#xff0c;JDK、JRE和JVM是三个经常听到的术语。 对于初学者来说&#xff0c;它们的概念和区别可能会让人感到困惑。 这篇文章详细解释下三个组件的含义、它们之间的区别和联系。 一&#xff0c;JDK&#xff1a;Java Development Kit JDK是Java开发工具…

umi6.x + react + antd的项目增加403(无权限页面拦截),404,错误处理页面

首先在src/pages下创建403&#xff0c;404&#xff0c;ErrorBoundary 403 import { Button, Result } from antd; import { history } from umijs/max;const UnAccessible () > (<Resultstatus"403"title"403"subTitle"抱歉&#xff0c;您无权…