普利姆算法
基本介绍
普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树。意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(英语:Vertex (graph theory)),且其所有边的权值之和亦为最小。该算法于1930年由捷克数学家沃伊捷赫·亚尔尼克(英语:Vojtěch Jarník)发现;并在1957年由美国计算机科学家罗伯特·普里姆(英语:Robert C. Prim)独立发现;1959年,艾兹格·迪科斯彻再次发现了该算法。因此,在某些场合,普里姆算法又被称为DJP算法、亚尔尼克算法或普里姆-亚尔尼克算法。
案例
1)有胜利乡有7个村庄(A, B, C, D, E, F, G) ,现在需要修路把7个村庄连通
2)各个村庄的距离用边线表示(权) ,比如 A – B 距离 5公里
3)问:如何修路保证各个村庄都能连通,并且总的修建公路总里程最短?
最小生成树
这个问题本质上就是最小生成树问题,最小生成树:一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边。最小生成树可以用kruskal(克鲁斯卡尔)算法或prim(普里姆)算法求出。
思路
代码
import java.util.Arrays;
public class PrimAlgorithm {
public static void main(String[] args) {
char[] data = {'A','B','C','D','E','F','G'};
int [][]weight=new int[][]{ //10000表示不通
{10000,5,7,10000,10000,10000,2},
{5,10000,10000,9,10000,10000,3},
{7,10000,10000,10000,8,10000,10000},
{10000,9,10000,10000,10000,4,10000},
{10000,10000,8,10000,10000,5,4},
{10000,10000,10000,4,5,10000,6},
{2,3,10000,10000,4,6,10000},};
int vertex = data.length;
MGraph graph = new MGraph(vertex);
MinTree minTree = new MinTree();
minTree.createGraph(graph,vertex,data,weight);
minTree.showGraph(graph);
minTree.prim(graph,0);
}
}
class MGraph {
int vertex; //顶点个数
char[] data; //存放顶点
int[][] weight; //邻接矩阵
public MGraph(int vertex) {
this.vertex = vertex;
weight = new int[vertex][vertex];
data = new char[vertex];
}
}
class MinTree {
/**
* 创建图的邻接矩阵
* @param graph 图对象
* @param vertex 图顶点个数
* @param data 图的顶点的值
* @param weight 图对应的邻接矩阵
*/
public void createGraph(MGraph graph,int vertex,char[] data,int[][] weight) {
int i, j;
for(i = 0; i < vertex; i++) {
graph.data[i] = data[i];
for(j = 0; j < vertex; j++) {
graph.weight[i][j] = weight[i][j];
}
}
}
/**
* 显示图的邻接矩阵
* @param graph 图对象
*/
public void showGraph(MGraph graph) {
for (int[] link : graph.weight) {
System.out.println("link = " + Arrays.toString(link));
}
}
/**
* 普利姆算法
* @param graph 图对象
* @param v 表示从哪个顶点开始
*/
public void prim(MGraph graph,int v) {
int[] visited = new int[graph.vertex]; //0表示未使用,1表示已使用
visited[v] = 1;
int index1 = 0;
int index2 = 0;
int minWeight = Integer.MAX_VALUE; //假设最小权值
for (int i = 1; i < graph.vertex; i++) {
for (int j = 0; j < graph.vertex; j++) {
for (int k = 0; k < graph.vertex; k++) {
if (visited[j] == 1 && visited[k] == 0 && graph.weight[j][k] < minWeight) {
minWeight = graph.weight[j][k];
index1 = j;
index2 = k;
}
}
}
System.out.println("边为=>" + graph.data[index1] + ">" + graph.data[index2] + ",权值是" + minWeight);
visited[index2] = 1;
minWeight = Integer.MAX_VALUE;
}
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)