Prime算法构造最小生成树(加点法)
一、算法逻辑
想要轻松形象理解Prime的算法逻辑,视频肯定比图文好。
小编看过很多求相关的教学视频,这里选出一个我认为最好理解的这一款安利给大家。
因为他不仅讲解细致,而且还配合了动画演示,可以说把一个抽象的东西讲的非常的形象了。
B站链接:【图-最小生成树-Prim(普里姆)算法】
接下来,小编会对视频中的算法补充一个java的具体实现
二、java实现
只用一个接口,写的代码,肯定不好理解,因为涉及到图的操作,所以这里先给一下基本的图的代码(使用邻接矩阵):
class Constant {public static final int MAX=Integer.MAX_VALUE;
}public class GraphByMatrix {private char[] arrayV;//顶点数组private int[][] matrix;//矩阵,存放每一个边的权重private boolean isDirect;//是否是有向图/*** 构造方法** @param size 代表当前顶点的个数* @param isDirect 是否是有向图,true是有向图*/public GraphByMatrix(int size, boolean isDirect) {this.arrayV = new char[size];//顶点的个数是sizematrix = new int[size][size];for (int i = 0; i < size; i++) {Arrays.fill(matrix[i], Constant.MAX);}this.isDirect = isDirect;}/*** @param srcV 起点* @param destV 终点* @param weight 权值*/public void addEdge(char srcV, char destV, int weight) {//重载之一,用来建立普通图int srcIndex = getIndexOfV(srcV);int destIndex = getIndexOfV(destV);matrix[srcIndex][destIndex] = weight;//如果是无向图 那么相反的位置 也同样需要置为空if (!isDirect) {matrix[destIndex][srcIndex] = weight;}}/*** @param srcIndex 起点* @param desIndex 终点* @param weight 权重*/public void addEdge(int srcIndex, int desIndex, int weight) {//重载两个之一,用来建立最小生成树matrix[srcIndex][desIndex] = weight;//如果是无向图 那么相反的位置 也同样需要置为空if (!isDirect) {matrix[desIndex][srcIndex] = weight;}}/*** 获取顶点V的下标** @param v* @return*/private int getIndexOfV(char v) {for (int i = 0; i < arrayV.length; i++) {if (arrayV[i] == v) {return i;}}return -1;}/*** 定义了一个边的抽象类* 用来存储边的*/static class Edge {public int srcIndex;public int destIndex;public int weight;//权重public Edge(int srcIndex, int destIndex, int weight) {this.srcIndex = srcIndex;this.destIndex = destIndex;this.weight = weight;}}public static void main(String[] args) {}
}
了解了上面的代码,看这个普利姆算法的接口就容易了:
/*** 普利姆算法* 最小生成树** @param minTree 要生成的树* @param V 选择的一个顶点*/public int prim(GraphByMatrix minTree, char V) {//需要先给一个顶点,作为起点int indexSrc = getIndexOfV(V);//获取起始顶点的下标/** 把顶点分成两个集合* 第一个集合存储已经确定好是minTree的一个顶点* 第二个存储还未确定的顶点** */int n = arrayV.length;//存的值,就是顶点的下标Set<Integer> setX = new HashSet<>(n);//长度就是所有顶点的大小,用来存确定的顶点Set<Integer> setY = new HashSet<>(n);//用来存还没有确定的顶点setX.add(indexSrc);//起始顶点已经是确定好了的,所以直接放到setX这个集合中//接下来,把除了起始顶点外的其他顶点都放到setY这个集合中(也就是还未确定的顶点)for (int i = 0; i < n; i++) {if (i != indexSrc) setY.add(i);}/** 定义一个优先级队列(小根堆,因为有得到最小权值),用来存储还没有确定好的 从确定顶点到没有确定顶点的边*/PriorityQueue<Edge> minHeap = new PriorityQueue<>((o1, o2) -> o1.weight - o2.weight);//默认是建立小根堆(因为是自定义类型,要重写compareTo)//接下来把从起始顶点 连接 到其他顶点的边都放到优先级队列中for (int i = 0; i < n; i++) {if (matrix[indexSrc][i] != Constant.MAX) {//从起始顶点->另一个没有确定的顶点存在(等于MAX代表不存在),就放到队列minHeap.offer(new Edge(indexSrc, i, matrix[indexSrc][i]));}}int totalWeight = 0;//用来记录总的权值int edgeN = 0;//用来记录已经确定的边while (edgeN != n - 1 && !minHeap.isEmpty()) {//只要没有加边到最小生成树,并且队列没有空,就一直加边//出队一个元素Edge edge = minHeap.poll();//判断这个边的 目标顶点 是否 在setX(已经确定的顶点)中if (!setX.contains(edge.destIndex)) {//如果不在,那么把这个边,放到最小生成树中//放到最小生成树minTree.addEdge(edge.srcIndex, edge.destIndex, edge.weight);//放完一个边,就记得edgeN++ 更新权重edgeN++;totalWeight += edge.weight;//记住把对应的顶点确定setX.add(edge.destIndex);//同时,在setY中删除对应目标顶点setY.remove(edge.destIndex);/** 到了这里,因为已经确定了一个新的顶点,* 因此,还要在这个新的顶点的基础上,* 入队从新顶点指向其他顶点的边* */for (int i = 0; i < n; i++) {if (matrix[edge.destIndex][i] != Constant.MAX && !setX.contains(i)) {//只要有边,并且不会形成环,那么入队minHeap.offer(new Edge(edge.destIndex, i, matrix[edge.destIndex][i]));}}}/*else{如果在setY就不做操作,如果继续放到minTree中,会形成环!!!}*/}if (edgeN == n - 1) return totalWeight;elsereturn -1;//没有找到,返回-1}
相关文章:
Prime算法构造最小生成树(加点法)
一、算法逻辑 想要轻松形象理解Prime的算法逻辑,视频肯定比图文好。 小编看过很多求相关的教学视频,这里选出一个我认为最好理解的这一款安利给大家。 因为他不仅讲解细致,而且还配合了动画演示,可以说把一个抽象的东西讲的非常…...
【VTKExamples::Utilities】第五期 CommandSubclass
很高兴在雪易的CSDN遇见你 VTK技术爱好者 QQ:870202403 公众号:VTK忠粉 前言 本文分享VTK样例CommandSubclass,希望对各位小伙伴有所帮助! 感谢各位小伙伴的点赞+关注,小易会继续努力分享,一起进步! 你的点赞就是我的动力(^U^)ノ~YO 1. CommandSubclass …...
重生之 SpringBoot3 入门保姆级学习(04、 包扫描)
重生之 SpringBoot3 入门保姆级学习(04、 包扫描) 2.1 包扫描 2.1 包扫描 默认包扫描规则: SpringBootApplication 标注的就是主程序 SpringBoot 只会扫描主程序下面的包 自动的 component-scan 功能 在 SpringBootApplication 添加参数可以…...
VectorDBBench在windows的调试
VectorDBBench在windows的调试 VectorDBBench是一款向量数据库基准测试工具,支持milvus、Zilliz Cloud、Elastic Search、Qdrant Cloud、Weaviate Cloud 、 PgVector、PgVectorRS等,可以测试其QPS、时延、recall。 VectorDBBench是一款使用python编写的…...
KAN(Kolmogorov-Arnold Network)的理解 1
系列文章目录 第一部分 KAN的理解——数学背景 文章目录 系列文章目录前言KAN背后的数学原理:Kolmogorov-Arnold representation theorem 前言 这里记录我对于KAN的探索过程,每次会尝试理解解释一部分问题。欢迎大家和我一起讨论。 KAN tutorial KAN背…...
Vue 项目中使用 Element UI库(Element UI 是一套基于 Vue.js 的桌面端组件库)
1. 安装 Element UI npm install element-plusnext 2.引入 Element UI(在main.js中引入组件,注意要引入.css文件,图标也要单独引用) import { createApp } from vueimport ElementPlus from element-plusimport element-plus/dist/index.css…...
C++240527
定义自己的命名空间 my_sapce,在 my_sapce 中定义 string 类型的变量 s1,再 定义一个函数 完成 对字符串的逆置 。 #include <iostream>//导入 标准命名空间,cout 和 endl 标识符 存在于标准命名空间中 using namespace std;//定义了自…...
揭秘动态网页爬取:步骤与实战技巧
新书上架~👇全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我👆,收藏下次不迷路┗|`O′|┛ 嗷~~ 目录 一、引言 二、动态网页爬取步骤 三、实战技巧分享 四、总结 一、引言 在大数据时代&#…...
Lvm逻辑卷调整容量
1、拉伸逻辑卷调整容量 [rootdesktop ~]# df ‐hT Filesystem Type Size Used Avail Use% Mounted on /dev/sda1 xfs 9.8G 3.3G 6.5G 34% / devtmpfs devtmpfs 660M 0 660M 0% /dev tmpfs tmpfs 674M 0 674M 0% /dev/shm tmpfs tmpfs 674M 8.9M 666M 2% /run tmpfs tmpfs 674M …...
CLIP源码详解:clip.py 文件
前言 这是关于 CLIP 源码中的 clip.py 文件中的代码带注释版本。 clip.py 文件的作用:封装了 clip 项目的相关 API,通过这些 API ,我们可以轻松使用 CLIP 项目预训练好的模型进行自己项目的应用。 另外不太容易懂的地方都使用了二级标题强…...
linux下重启oracle数据库步骤
Linux下重启oracle数据库步骤: 1.使用oracle用户登录数据库服务器(root登录的话进入数据库时会找不到sqlplus命令) su – oracle 2.通过数据库管理员sysdba进入oracle数据库 sqlplus / as sysdba 3.关闭数据库 shutdown immediate ࿰…...
[自动驾驶技术]-1 概述技术和法规
自动驾驶(Autonomous Driving),也称为无人驾驶或自驾,是指通过计算机系统和传感器设备,自动驾驶汽车在没有人类干预的情况下能够感知环境并做出驾驶决策,从而实现车辆的自主行驶。 自动驾驶技术层级 自动…...
Qt自定义标题栏
效果如下: 代码如下: // widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget>QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *parent nullptr…...
java如何向数组中插入元素
java的数组是不可改变的,因此如果要向数组中插入新的元素,需要新建一个数组,新的数组元素个数减去老数组元素个数的差大于等于要插入新的元素数量。 假如说要插入一个数组元素,需要把新元素插入到中间,把新的数组分为…...
4、PHP的xml注入漏洞(xxe)
青少年ctf:PHP的XXE 1、打开网页是一个PHP版本页面 2、CTRLf搜索xml,发现2.8.0版本,含有xml漏洞 3、bp抓包 4、使用代码出发bug GET /simplexml_load_string.php HTTP/1.1 补充: <?xml version"1.0" encoding&quo…...
设计模式-解释器模式
作者持续关注 WPS二次开发专题系列,持续为大家带来更多有价值的WPS开发技术细节,如果能够帮助到您,请帮忙来个一键三连,更多问题请联系我(QQ:250325397) 定义 解释器模式(Interpreter Pattern&…...
NDIS驱动程序堆栈
NDIS 6.0 引入了暂停和重启驱动程序堆栈的功能。 若要支持 NDIS 6.0 提供的堆栈管理功能,必须重写旧版驱动程序。 NDIS 6.0 还引入了 NDIS Filter驱动程序。 Filter驱动程序可以监视和修改协议驱动程序与微型端口驱动程序之间的交互。 与 NDIS 5 相比,F…...
大数据开发面试题【数仓篇】
197、数据仓库和传统数据库区别 由于历史数据使用频率过低,导致数据堆积,查询性能下降;用于查询分析,涉及大量的历史数据,数据仓库中的数据一般来日志文件和事务 数据库是跟业务挂钩的,数据库不可能装下一…...
Leetcode刷题笔记5
76. 最小覆盖子串 76. 最小覆盖子串 - 力扣(LeetCode) 解法一: 暴力枚举 哈希表 先定义left和right,可以在随机位置 枚举一个位置向后找,找到一个位置之后,发现这段区间是一个最小的区间之后,…...
【Qt】Qt中的信号槽
一、信号和槽概述 信号槽是Qt矿建引以为豪的机制之一。 所谓信号槽,实际上就是观察者模式(发布——订阅模式)。当某个事件发生之后,比如,按钮检测到自己被点击了一下,它就会发出一个信号。这种发出的信号是…...
基于大模型的 UI 自动化系统
基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...
基于服务器使用 apt 安装、配置 Nginx
🧾 一、查看可安装的 Nginx 版本 首先,你可以运行以下命令查看可用版本: apt-cache madison nginx-core输出示例: nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...
Python爬虫(二):爬虫完整流程
爬虫完整流程详解(7大核心步骤实战技巧) 一、爬虫完整工作流程 以下是爬虫开发的完整流程,我将结合具体技术点和实战经验展开说明: 1. 目标分析与前期准备 网站技术分析: 使用浏览器开发者工具(F12&…...
第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明
AI 领域的快速发展正在催生一个新时代,智能代理(agents)不再是孤立的个体,而是能够像一个数字团队一样协作。然而,当前 AI 生态系统的碎片化阻碍了这一愿景的实现,导致了“AI 巴别塔问题”——不同代理之间…...
vue3 定时器-定义全局方法 vue+ts
1.创建ts文件 路径:src/utils/timer.ts 完整代码: import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...
【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)
🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...
如何理解 IP 数据报中的 TTL?
目录 前言理解 前言 面试灵魂一问:说说对 IP 数据报中 TTL 的理解?我们都知道,IP 数据报由首部和数据两部分组成,首部又分为两部分:固定部分和可变部分,共占 20 字节,而即将讨论的 TTL 就位于首…...
是否存在路径(FIFOBB算法)
题目描述 一个具有 n 个顶点e条边的无向图,该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序,确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数,分别表示n 和 e 的值(1…...
Kafka入门-生产者
生产者 生产者发送流程: 延迟时间为0ms时,也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于:异步发送不需要等待结果,同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...
