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

优先队列

理论知识

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)

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

RISCV 外部GCC 工具链安装@FreeBSD15

在交叉编译的时候&#xff0c;可以使用FreeBSD15默认的工具链&#xff1a;LLVM 也可以使用GCC工具链&#xff0c;GCC可以使用现成pkg包安装&#xff0c;也可以编译安装。 LLVM的特点是高移植性和高效&#xff0c;但学习成本高。GCC的特点是成熟稳定&#xff0c;但优化能力有限…

【系统架构师】-案例篇(五)企业应用系统集成与ESB

在航空业中&#xff0c;Ramp Coordination是指飞机从降落到起飞过程中所需要进行的各种业务活动的协调过程。通常每个航班都有一位员工负责Ramp Coordination&#xff0c;称之为RampCoordinator。由Ramp Coordinator协调的业务活动包括检查机位环境、卸货和装货等。 由于航班类…

2024C题生物质和煤共热解问题的研究 详细思路

背景 随着全球能源需求的不断增长和对可再生能源的追求&#xff0c;生物质和煤共热解作为一种潜在的能源转化技术备受关注。生物质是指可再生能源&#xff0c;源自植物和动物的有机物质&#xff0c;而煤则是一种化石燃料。** 在共热解过程中&#xff0c;生物质和煤在高温和缺氧…

数据库调优-SQL语句优化

2. SQL语句优化 sql 复制代码 # 请问这两条SQL语句有什么区别呢&#xff1f;你来猜一猜那条SQL语句执行查询效果更好&#xff01; select id from sys_goods where goods_name华为 HUAWEI 麦芒7 魅海蓝 6G64G 全网通; ​ select id from sys_goods where goods_id14967325985…

【科研】常用的实验结果评价指标(1) —— R2(R-square)是什么?

常用的实验结果评价指标&#xff08;1&#xff09; —— R2(R-square)&#xff0c;可能为负数吗&#xff1f;&#xff01; 提示&#xff1a;先说概念&#xff0c;后续再陆续上代码 文章目录 常用的实验结果评价指标&#xff08;1&#xff09; —— R2(R-square)&#xff0c;可能…

【电路笔记】-无源高通滤波器

无源高通滤波器 文章目录 无源高通滤波器1、概述2、一阶高通滤波器的频率响应3、高通滤波器示例4、二阶高通滤波器5、RC 差异化因素高通滤波器与低通滤波器电路完全相反,因为这两个组件已互换,滤波器输出信号现在从电阻器两端获取。 1、概述 由于低通滤波器只允许低于其截止…

Python中的多进程、多线程、协程

Python中的多线程、多进程、协程 一、概述 1. 多线程Thread &#xff08;threading&#xff09;&#xff1a; 优点&#xff1a;同一个进程中可以启动多个线程&#xff0c;充分利用IO时&#xff0c;cpu进行等待的时间缺点&#xff1a;相对于进程&#xff0c;多线程只能并发执…

Python写了for i in range(10)却只打印一遍?

题目&#xff1a;定义一个两个参数的重复打印函数&#xff0c;第一个参数指定要打印的字符串&#xff0c;第二个参数指定要重复打印的次数&#xff0c;在主程序中调用该函数&#xff0c;打印10遍你的学号姓名。 为什么调用函数后结果只打印了一遍? 看了题目感觉就很诡异&#…

AS-VJ900实时视频拼接系统产品介绍:两画面视频拼接方法和操作

目录 一、实时视频拼接系统介绍 &#xff08;一&#xff09;实时视频拼接的定义 &#xff08;二&#xff09;无缝拼接 &#xff08;三&#xff09;AS-VJ900功能介绍 1、功能 2、拼接界面介绍 二、拼接前的准备 &#xff08;一&#xff09;摄像机选择 &#xff08;二&a…

169.招式拆解 II(unordered_map)

刷算法题&#xff1a; 第一遍&#xff1a;1.看5分钟&#xff0c;没思路看题解 2.通过题解改进自己的解法&#xff0c;并且要写每行的注释以及自己的思路。 3.思考自己做到了题解的哪一步&#xff0c;下次怎么才能做对(总结方法) 4.整理到自己的自媒体平台。 5.再刷重复的类…

数据中心法

数据中心法是实现词法分析器的结构化方法。通过设计主表和子表分开存储状态转移信息&#xff0c;实现词法分析器的控制逻辑和数据结构分离。 主要解决了状态爆炸、难以维护和复杂性的问题。 状态爆炸是指当状态和转移较多时&#xff0c;单一使用一个表来存储所有的信息的话会导…

Paddle 实现DCGAN

传统GAN 传统的GAN可以看我的这篇文章&#xff1a;Paddle 基于ANN&#xff08;全连接神经网络&#xff09;的GAN&#xff08;生成对抗网络&#xff09;实现-CSDN博客 DCGAN DCGAN是适用于图像生成的GAN&#xff0c;它的特点是&#xff1a; 只采用卷积层和转置卷积层&#x…

如何在 CentOS 上安装并配置 Redis

如何在 CentOS 上安装并配置 Redis 但是太阳&#xff0c;他每时每刻都是夕阳也都是旭日。当他熄灭着走下山去收尽苍凉残照之际&#xff0c;正是他在另一面燃烧着爬上山巅散烈烈朝晖之时。 ——史铁生 环境准备 本教程将在 CentOS 7 或 CentOS 8 上进行。确保你的系统已更新到最…

自托管站点监控工具 Uptime Kuma 搭建与使用

本文首发于只抄博客&#xff0c;欢迎点击原文链接了解更多内容。 前言 Uptime Kuma 是一个类似 Uptime Robot 的站点监控工具&#xff0c;它可以自托管在自己的 Nas 或者 VPS 上&#xff0c;用来监控各类站点、数据库等 监控类型&#xff1a;支持监控 HTTP(s) / TCP / HTTP(s…

Day 43 1049. 最后一块石头的重量 II 494. 目标和 474.一和零

最后一块石头重量Ⅱ 有一堆石头&#xff0c;每块石头的重量都是正整数。 每一回合&#xff0c;从中选出任意两块石头&#xff0c;然后将它们一起粉碎。假设石头的重量分别为 x 和 y&#xff0c;且 x < y。那么粉碎的可能结果如下&#xff1a; 如果 x y&#xff0c;那么两…

【LLM 论文】Step-Back Prompting:先解决更高层次的问题来提高 LLM 推理能力

论文&#xff1a;Take a Step Back: Evoking Reasoning via Abstraction in Large Language Models ⭐⭐⭐⭐ Google DeepMind, ICLR 2024, arXiv:2310.06117 论文速读 该论文受到的启发是&#xff1a;人类再解决一个包含很多细节的具体问题时&#xff0c;先站在更高的层次上解…

【Git】Github创建远程仓库并与本地互联

创建仓库 点击生成新的仓库 创建成功后会生成一个这样的文件 拉取到本地 首先先确保本地安装了git 可以通过终端使用 git --version来查看是否安装好了git 如果显示了版本信息&#xff0c;说明已经安装好了git&#xff0c;这时候我们就可以进入我们想要clone到问目标文件夹 …

计算机系列之算法分析与设计

21、算法分析与设计 算法是对特定问题求解步骤的一种描述。它是指令的有限序列&#xff0c;其中每一条指令标识一个或多个操作。 它具有有穷性、确定性&#xff08;含义确定、输入输出确定&#xff0c;相同输入相同输出&#xff1b;执行路径唯一&#xff09;、可行性、输入&a…

【SAP ME 38】SAP ME发布WebService配置及应用

更多WebService介绍请参照 【SAP ME 28】SAP ME创建开发组件&#xff08;DC&#xff09;webService 致此一个WebService应用发布成功&#xff0c;把wsdl文件提供到第三方系统调用接口&#xff01; 注意&#xff1a; 在SAP ME官方开发中默认对外开放的接口是WebService接口&am…

01、vue+openlayers6实现自定义测量功能(提供源码)

首先先封装一些openlayers的工具函数&#xff0c;如下所示&#xff1a; import VectorSource from ol/source/Vector; import VectorLayer from ol/layer/Vector; import Style from ol/style/Style; import Fill from ol/style/Fill; import Stroke from ol/style/Stroke; im…