当前位置: 首页 > news >正文

Java 语言实现最小生成树算法(如Prim算法、Kruskal算法)

引言:
在图论中,最小生成树是指一个无向图的生成树,其所有边的权值之和最小。解决最小生成树问题的两种主要算法是Prim算法和Kruskal算法。本文将深入探讨这两种算法并比较它们的优缺点,以帮助读者更好地理解最小生成树算法的原理和实现。

一、Prim算法

  1. 算法原理
    Prim算法是一种贪心算法,通过逐步扩展生成树的边来构造最小生成树。算法开始时选择一个起始顶点,然后将该顶点添加到生成树中。之后,每次将离生成树最近的顶点添加到生成树中,并将所选顶点与其余顶点的边进行比较,选择最小边加入生成树,直至所有顶点都加入生成树。

  2. 算法步骤

    1. 创建一个空的生成树和一个空的顶点集合;
    2. 选择一个起始顶点,将其加入生成树,并将其标记为已访问;
    3. 重复以下步骤,直到所有顶点都加入生成树:
      a) 从已访问的顶点中,选择一条边的权值最小的未访问顶点;
      b) 将该未访问顶点加入生成树,并将其标记为已访问;
      c) 更新生成树和未访问顶点的权值。
  3. 算法实现
    实现Prim算法的关键是选择起始顶点和找到离生成树最近的未访问顶点。可以使用优先队列等数据结构来快速找到最小边。

二、Kruskal算法

  1. 算法原理
    Kruskal算法是一种基于边的贪心算法,通过逐渐选择权值最小的边来构造最小生成树。算法将图中所有边按照权值从小到大排序,然后从最小权值的边开始逐一添加到生成树中,直到生成树包含了所有顶点。

  2. 算法步骤

    1. 创建一个空的生成树和一个空的边集合;
    2. 将图中所有边按照权值从小到大排序;
    3. 逐一选择未加入生成树的边,如果该边的两个顶点不在同一个连通分量中,则将该边加入生成树,并将两个顶点合并为一个连通分量;
    4. 重复步骤3,直到生成树包含了所有顶点。
  3. 算法实现
    实现Kruskal算法的关键是边的排序和判断两个顶点是否在同一个连通分量中。可以使用并查集等数据结构来快速判断连通分量,并在添加边时更新并查集。

三、Prim算法 vs Kruskal算法

  1. 时间复杂度
    Prim算法的时间复杂度为O(|V|^2),其中|V|表示顶点数。Kruskal算法的时间复杂度为O(|E|log|E|),其中|E|表示边数。从时间复杂度上来看,当图稠密时,Prim算法的效率更高,而当图稀疏时,Kruskal算法效率更高。

  2. 空间复杂度
    Prim算法和Kruskal算法的空间复杂度均为O(|V|+|E|),其中|V|表示顶点数,|E|表示边数。

  3. 适用性
    Prim算法适用于带权值的稠密图,而Kruskal算法适用于带权值的稀疏图。此外,如果需要在不连通的图中找出最小生成树,Kruskal算法是更好的选择。

结论:
最小生成树算法是图算法中重要且实用的算法之一。本文深入探讨了Prim算法和Kruskal算法的原理和实现,并比较了它们的优缺点。根据具体问题的特点和数据的特征,可以选择适合自己的算法来解决最小生成树问题。

import java.util.*;class Edge {int src, dest, weight;Edge(int src, int dest, int weight) {this.src = src;this.dest = dest;this.weight = weight;}
}class Graph {int V, E;List<Edge> edges;Graph(int vertices, int edges) {this.V = vertices;this.E = edges;this.edges = new ArrayList<>();}void addEdge(int src, int dest, int weight) {Edge edge = new Edge(src, dest, weight);edges.add(edge);}// Prim's algorithm for Minimum Spanning Treevoid primMST() {int[] parent = new int[V];int[] key = new int[V];boolean[] mstSet = new boolean[V];// Initialize key and mstSet arraysfor (int i = 0; i < V; i++) {key[i] = Integer.MAX_VALUE;mstSet[i] = false;}key[0] = 0;parent[0] = -1;for (int count = 0; count < V - 1; count++) {int u = getMinimumKey(key, mstSet);mstSet[u] = true;for (Edge edge : edges) {if (edge.src == u && !mstSet[edge.dest] && edge.weight < key[edge.dest]) {parent[edge.dest] = u;key[edge.dest] = edge.weight;}}}printMST(parent, key);}int getMinimumKey(int[] key, boolean[] mstSet) {int min = Integer.MAX_VALUE;int minIndex = -1;for (int v = 0; v < V; v++) {if (!mstSet[v] && key[v] < min) {min = key[v];minIndex = v;}}return minIndex;}void printMST(int[] parent, int[] key) {System.out.println("Prim's Minimum Spanning Tree:");System.out.println("Edge \tWeight");for (int i = 1; i < V; i++) {System.out.println(parent[i] + " - " + i + "\t" + key[i]);}}// Kruskal's algorithm for Minimum Spanning Treevoid kruskalMST() {List<Edge> result = new ArrayList<>();Collections.sort(edges, Comparator.comparingInt(edge -> edge.weight));UnionFind uf = new UnionFind(V);for (Edge edge : edges) {int srcRoot = uf.find(edge.src);int destRoot = uf.find(edge.dest);if (srcRoot != destRoot) {result.add(edge);uf.union(srcRoot, destRoot);}}printMST(result);}void printMST(List<Edge> result) {System.out.println("Kruskal's Minimum Spanning Tree:");System.out.println("Edge \tWeight");for (Edge edge : result) {System.out.println(edge.src + " - " + edge.dest + "\t" + edge.weight);}}
}class UnionFind {int[] parent;int[] rank;UnionFind(int n) {parent = new int[n];rank = new int[n];for (int i = 0; i < n; i++) {parent[i] = i;}}int find(int x) {if (parent[x] != x) {parent[x] = find(parent[x]);}return parent[x];}void union(int x, int y) {int xRoot = find(x);int yRoot = find(y);if (rank[xRoot] < rank[yRoot]) {parent[xRoot] = yRoot;} else if (rank[xRoot] > rank[yRoot]) {parent[yRoot] = xRoot;} else {parent[yRoot] = xRoot;rank[xRoot]++;}}
}public class Main {public static void main(String[] args) {int V = 4;int E = 5;Graph graph = new Graph(V, E);graph.addEdge(0, 1, 10);graph.addEdge(0, 2, 6);graph.addEdge(0, 3, 5);graph.addEdge(1, 3, 15);graph.addEdge(2, 3, 4);graph.primMST();System.out.println();graph.kruskalMST();}
}

这是一个使用Java语言实现的最小生成树算法的示例代码。代码中包含了Prim算法和Kruskal算法的实现,并提供了一个简单的图示例进行测试。通过调用primMST()kruskalMST()方法,可以分别使用Prim算法和Kruskal算法计算出图的最小生成树,并将结果打印到控制台上。

在示例代码中,Graph类表示一个图,primMST()方法实现了Prim算法,kruskalMST()方法实现了Kruskal算法。辅助类Edge表示图中的边,UnionFind类实现了并查集用于Kruskal算法中的连通性判断。

通过运行示例代码,可以看到Prim算法和Kruskal算法分别计算出的最小生成树结果,并输出到控制台上。可以根据自己的需求和图的特点,使用不同的算法来解决最小生成树问题。

相关文章:

Java 语言实现最小生成树算法(如Prim算法、Kruskal算法)

引言&#xff1a; 在图论中&#xff0c;最小生成树是指一个无向图的生成树&#xff0c;其所有边的权值之和最小。解决最小生成树问题的两种主要算法是Prim算法和Kruskal算法。本文将深入探讨这两种算法并比较它们的优缺点&#xff0c;以帮助读者更好地理解最小生成树算法的原理…...

什么是Linux的Overcommit和OOM

overcommit_memory参数说明&#xff1a; 设置内存分配策略&#xff08;可选&#xff0c;根据服务器的实际情况进行设置&#xff09; /proc/sys/vm/overcommit_memory 可选值&#xff1a;0、1、2。 0&#xff0c; 表示内核将检查是否有足够的可用内存供应用进程使用&#xf…...

解决防火墙导致虚拟机不能ping通宿主机的问题

今天&#xff0c;无缘无故的&#xff0c;虚拟机突然用不了&#xff0c;网络连上不了&#xff0c;一番折腾翻找&#xff0c;最后才发现&#xff0c;是因为虚拟机ping不同宿主主机了&#xff0c;连网关都ping不通了&#xff0c;但是&#xff0c;宿主主机却可以ping通虚拟机 。 最…...

数据结构:线性表(栈的实现)

文章目录 1. 栈(Stack)1.1 栈的概念1.2 栈的结构链表栈数组栈 2. 栈的定义3. 栈的实现3.1 初始化栈 (StackInit)3.2 入栈 (StackPush)3.3 出栈 (StackPop)3.4 检测栈是否为空 (StackEmpty)3.5 获取栈顶元素 (StackTop)3.6 获取栈中有效元素个数 (StackSize)3.7 销毁栈 (StackDe…...

python如何将一个dataframe快速写入clickhouse

目录 前言思路与核心代码优缺点分析 前言 dataframe是用python做数据分析最场景的数据结构了&#xff0c;如何将dataframe数据快速写入到clickhouse数据库呢&#xff1f;这里介绍几种方法&#xff0c;各有优劣势&#xff0c;可以结合自己的使用场景挑用。 思路与核心代码 假…...

Tiny Player Mac:小而美,音乐播放的极致体验

对于追求音质和操作简便的Mac用户来说&#xff0c;Tiny Player Mac是一款不可多得的音乐播放器。它以简洁的界面、强大的功能和优异的性能&#xff0c;吸引了无数用户的目光。接下来&#xff0c;让我们一起了解这款小而美的音乐播放器。 Tiny Player Mac支持多种音频格式&#…...

2022年12月 C/C++(五级)真题解析#中国电子学会#全国青少年软件编程等级考试

C/C++编程(1~8级)全部真题・点这里 第1题:漫漫回国路 2020年5月,国际航班机票难求。一位在美国华盛顿的中国留学生,因为一些原因必须在本周内回到北京。现在已知各个机场之间的航班情况,求问他回不回得来(不考虑转机次数和机票价格)。 时间限制:1000 内存限制:65536 …...

C语言学习:7、break与continue的用法

前面讲到的循环体&#xff0c;貌似能解决生活中的很多问题&#xff0c;毕竟生活中很多事情是在重复的。但有时候也会有些小插曲&#xff0c;比如你在日复一日的上班&#xff0c;但某一天又特殊的事情你失业了&#xff0c;不就没班上了吗&#xff0c;那就得跳出那个上班的循环了…...

Ubuntu中安装clion并把clion添加到桌面快捷方式

Clion的安装&#xff1a; CLion是由大名鼎鼎的JetBrains公司出品的一款面向C和C的集成开发工具。下载地址。 下载后解压出来&#xff0c;然后进入到解压后的文件夹里面&#xff0c;执行 ./clion.sh 便可以运行软件&#xff1a; cd bin/ ./clion.sh 激活使用的话&…...

如何利用python来提取SQL语句中的表名称

1.介绍 在某些场景下&#xff0c;我们可能需要从一个复杂的SQL语句中提取对应的表名称&#xff0c;在这样的场景下&#xff0c;我们如果在python中处理的话&#xff0c;就需要用到SQLparse这个库。 SQLparse 是一个用于解析 SQL 查询语句的 Python 库。它可以将复杂的 SQL 查询…...

linux通用时钟框架(CCF)

目录 前言CCF 介绍提供者和消费者的概念CCF 框架组成关系CCF 程序关键结构体 CCF 重要组成注册时钟未使用设备树的时钟注册操作使用设备树的时钟注册操作 从使用的角度看CCF 前言 linux 内核版本 v4.19 嵌入式平台rv1109 , 文中代码出处。 CCF 介绍 提供者和消费者的概念 C…...

基于AERMOD模型在大气环境影响评价中的实践技术应用

随着我国经济快速发展&#xff0c;我国面临着日益严重的大气污染问题。近年来&#xff0c;严重的大气污染问题已经明显影响国计民生&#xff0c;引起政府、学界和人们越来越多的关注。大气污染是工农业生产、生活、交通、城市化等方面人为活动的综合结果&#xff0c;同时气象因…...

企业内训课程、在线教育平台付费课程加密防下载的10种方式

企业内训课程、在线教育平台付费课程加密防下载的10种方式&#xff1a; 实例演示&#xff1a;课程视频-第1课状语从句,VRM演示应用 企业内训课程、在线教育平台付费课程&#xff0c;他们的这种视频课程的加密是如何做的&#xff1f;整理了10种思路&#xff0c;供大家参考&…...

公关世界杂志公关世界杂志社公关世界编辑部2023年第14期目录

封面印象 画里有大美 笔下有乾坤——品读吴建潮的绘画艺术和诗文创作 赵铁信; 4-9 专题报道 “安济欣看千年济&#xff0c;李春赢得万口春”——赵州桥诗词楹联文化鉴赏暨沈鹏书法艺术研讨会举行 刘占行; 10-14 中国书协第二三届理事、河北省书协原副主席兼秘书长、…...

Linux常用(实用)命令大全

pwd 显示当前工作路径 shutdown 关闭系统 /halt 关闭系统 shutdown -r now 重启 /reboot 重启 systemctl stop firewalld 关闭防火墙 ip addr 查看ip地址. 1、cd命令&#xff1a;用于切换当前目录&#xff08;可以是绝对路径&#xff0c;也可以是相对路径&#xff09;如&#x…...

2023-09-07力扣每日一题

链接&#xff1a; [2594. 修车的最少时间](https://leetcode.cn/problems/form-smallest-number-from-two-digit-arrays/) 题意&#xff1a; 一个能力R的人R*N*N分钟修N辆车&#xff0c;求最快多久修完&#xff08;多人多车&#xff09; 解&#xff1a; 二分很好想&#x…...

从C语言到C++_39(C++笔试面试题)next_permutation刷力扣

这篇就一直更新一些C的选择题和编程题了。 目录 笔试题1 答案及解析1 笔试题2 答案及解析2 力扣编程题 88. 合并两个有序数组 解析代码 349. 两个数组的交集 解析代码 60. 排列序列 解析代码 46. 全排列 解析代码 本篇完。 笔试题1 1. 以下哪种STL容器中的对象…...

适用于Linux的Windows子系统(系统安装步骤)

目录 前言 一、WSL2安装 1.Microsoft参考文档&#xff08;推荐选择旧版 WSL 的手动安装步骤&#xff09; 2.开启子系统 二、Ubuntu安装 1.在Microsoft Store中获取ubuntu 2.运行ubuntu配置管理信息 3.ubuntu换源 三、WSL 与 Ubuntu的一些基础使用命令 四、Windows Terminal终端…...

HarmonyOS/OpenHarmony(Stage模型)应用开发组合手势(二)并行识别

并行识别组合手势对应的GestureMode为Parallel。并行识别组合手势中注册的手势将同时进行识别&#xff0c;直到所有手势识别结束。并行识别手势组合中的手势进行识别时互不影响。 以在一个Column组件上绑定点击手势和双击手势组成的并行识别手势为例&#xff0c;由于单击手势和…...

如何使用GPT引领前沿与应用突破之GPT4科研实践技术与AI绘图

GPT对于每个科研人员已经成为不可或缺的辅助工具&#xff0c;不同的研究领域和项目具有不同的需求。例如在科研编程、绘图领域&#xff1a; 1、编程建议和示例代码: 无论你使用的编程语言是Python、R、MATLAB还是其他语言&#xff0c;都可以为你提供相关的代码示例。 2、数据可…...

React19源码系列之 事件插件系统

事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...

前端开发面试题总结-JavaScript篇(一)

文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包&#xff08;Closure&#xff09;&#xff1f;闭包有什么应用场景和潜在问题&#xff1f;2.解释 JavaScript 的作用域链&#xff08;Scope Chain&#xff09; 二、原型与继承3.原型链是什么&#xff1f;如何实现继承&a…...

c#开发AI模型对话

AI模型 前面已经介绍了一般AI模型本地部署&#xff0c;直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型&#xff0c;但是目前国内可能使用不多&#xff0c;至少实践例子很少看见。开发训练模型就不介绍了&am…...

《C++ 模板》

目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板&#xff0c;就像一个模具&#xff0c;里面可以将不同类型的材料做成一个形状&#xff0c;其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式&#xff1a;templa…...

基于 TAPD 进行项目管理

起因 自己写了个小工具&#xff0c;仓库用的Github。之前在用markdown进行需求管理&#xff0c;现在随着功能的增加&#xff0c;感觉有点难以管理了&#xff0c;所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD&#xff0c;需要提供一个企业名新建一个项目&#…...

人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式

今天是关于AI如何在教学中增强学生的学习体验&#xff0c;我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育&#xff0c;这并非炒作&#xff0c;而是已经发生的巨大变革。教育机构和教育者不能忽视它&#xff0c;试图简单地禁止学生使…...

uniapp手机号一键登录保姆级教程(包含前端和后端)

目录 前置条件创建uniapp项目并关联uniClound云空间开启一键登录模块并开通一键登录服务编写云函数并上传部署获取手机号流程(第一种) 前端直接调用云函数获取手机号&#xff08;第三种&#xff09;后台调用云函数获取手机号 错误码常见问题 前置条件 手机安装有sim卡手机开启…...

MySQL 主从同步异常处理

阅读原文&#xff1a;https://www.xiaozaoshu.top/articles/mysql-m-s-update-pk MySQL 做双主&#xff0c;遇到的这个错误&#xff1a; Could not execute Update_rows event on table ... Error_code: 1032是 MySQL 主从复制时的经典错误之一&#xff0c;通常表示&#xff…...

Java 与 MySQL 性能优化:MySQL 慢 SQL 诊断与分析方法详解

文章目录 一、开启慢查询日志&#xff0c;定位耗时SQL1.1 查看慢查询日志是否开启1.2 临时开启慢查询日志1.3 永久开启慢查询日志1.4 分析慢查询日志 二、使用EXPLAIN分析SQL执行计划2.1 EXPLAIN的基本使用2.2 EXPLAIN分析案例2.3 根据EXPLAIN结果优化SQL 三、使用SHOW PROFILE…...

2.3 物理层设备

在这个视频中&#xff0c;我们要学习工作在物理层的两种网络设备&#xff0c;分别是中继器和集线器。首先来看中继器。在计算机网络中两个节点之间&#xff0c;需要通过物理传输媒体或者说物理传输介质进行连接。像同轴电缆、双绞线就是典型的传输介质&#xff0c;假设A节点要给…...