Prim`s algorithm
- 概述
-
- 修路问题
概述
- 普里姆算法(Prim`s algorithm)是求出最小生成树的算法, 也就是在包含 n个顶点的带权无向连通图中, 找出(n-1)条边的最小耗费生成树(Minimum Cost Spanning Tree), 简称 MST
- 普里姆算法的时间复杂度为: 邻接矩阵 O(v^2), 邻接表 O(elog2v) e为网中的边数
修路问题
- 有叫(A,B,C,D,E,F,G)的7个村庄, 现在需要将这7个村庄通过修路连通. 各个村庄的距离用边线权值来表示, 比如 A-B距离5公里
- 需要保证各个村庄都能连通, 且修建公路的总里程为最短

- 求出最小生成树的步骤:
从顶点开始处理, 其中选出公里数最近的, 也就是 A-G(权值2): <A,G>
A-C(权值7),
, A-B(权值5)
A-G(权值2)
<A,G>开始, 将与 A和 G顶点相邻的, 且还未访问的顶点进行处理: <A,G,B>
A-C(权值7), A-B(权值5),
, G-E(权值4), G-F(权值6)
G-B(权值3)
<A,G,B>开始, 将与 A,G,B顶点相邻的, 且还未访问的顶点进行处理: <A,G,B,E>
A-C(权值7),
, G-F(权值6), B-D(权值9)
G-E(权值4)
- 处理 F <A,G,B,E,F>, 对应的边是
E-F(权值5)
- 处理 D <A,G,B,E,F,D>, 对应的边是
F-D(权值4)
- 处理 C <A,G,B,E,F,D,C>, 对应的边是
A-C(权值7)
- 代码实现
public class PrimAlgorithmApp {
public static void main(String[] args) {
/** 定义顶点(村庄)*/
char[] data = new char[] {'A','B','C','D','E','F','G'};
/** 设置邻接矩阵的顶点与顶点间的边(附带权值), 权值9999表示不连通*/
int[][] matrix = new int[][] {
{9999,5,7,9999,9999,9999,2},
{5,9999,9999,9,9999,9999,3},
{7,9999,9999,9999,8,9999,9999},
{9999,9,9999,9999,9999,4,9999},
{9999,9999,8,9999,9999,5,4},
{9999,9999,9999,4,5,9999,6},
{2,3,9999,9999,4,6,9999},};
/** 创建图实例*/
MSTGraph graph = new MSTGraph(data.length);
/** 创建最小生成树类实例*/
MinimumCostSpanningTree mst = new MinimumCostSpanningTree();
/** 创建邻接矩阵*/
mst.createGraph(graph, data, matrix);
/** 打印邻接矩阵*/
mst.showGraph(graph);
/** 求出最小生成树*/
mst.prim(graph, 1);
}
}
/** 定义最小生成树图类*/
class MSTGraph {
/** 顶点个数*/
int vertexCount;
/** 顶点数据*/
char[] vertexes;
/** 邻接矩阵*/
int[][] matrix;
public MSTGraph(int count) {
this.vertexCount = count;
vertexes = new char[count];
matrix = new int[count][count];
}
}
/** 定义创建最小生成树的类*/
class MinimumCostSpanningTree {
/** 创建邻接矩阵
* @param graph 图对象
* @param data 图的各个顶点的值
* @param matrix 图的邻接矩阵*/
public void createGraph(MSTGraph graph, char data[], int[][] matrix) {
int i, j;
for(i = 0; i < data.length; i++) {
graph.vertexes[i] = data[i];
for(j = 0; j < data.length; j++) {
graph.matrix[i][j] = matrix[i][j];
}
}
}
/** 打印邻接矩阵*/
public void showGraph(MSTGraph graph) {
for(int[] link: graph.matrix) {
System.out.println(Arrays.toString(link));
}
}
/** 求出最小生成树
* @param graph 图
* @param v 生成时, 起始顶点 'A'->0 'B'->1...*/
public void prim(MSTGraph graph, int v) {
/** 标记已被访问过的顶点, 按序每个顶点默认标记为0, 表示未访问过*/
int visited[] = new int[graph.vertexCount];
/** 将当前顶点标记为已访问*/
visited[v] = 1;
/** 临时存储已访问顶点下标*/
int h1 = -1;
/** 临时存储未访问顶点下标*/
int h2 = -1;
/** 初始权值设为9999表示不连通*/
int minWeight = 9999;
/** 最小生成树的最终边个数为 graph.vertexCount-1个*/
for(int k = 1; k < graph.vertexCount; k++) {
for(int i = 0; i < graph.vertexCount; i++) { /** i表示已被访问过的顶点*/
for(int j = 0; j< graph.vertexCount;j++) { /** i表示未访问过的顶点*/
/** 已访问的顶点 && 未访问的顶点 && 公里(权值)可达*/
if(visited[i] == 1 && visited[j] == 0 && graph.matrix[i][j] < minWeight) {
minWeight = graph.matrix[i][j];
h1 = i;
h2 = j;
}
}
}
/** 找到一条边是最小的可达边*/
System.out.println("边<" + graph.vertexes[h1] + "," + graph.vertexes[h2] + "> 权值: " + minWeight);
/** 将当前节点标记为已经访问*/
visited[h2] = 1;
/** 重新将 minWeight设为不连通*/
minWeight = 9999;
}
}
}
输出:
[9999, 5, 7, 9999, 9999, 9999, 2]
[5, 9999, 9999, 9, 9999, 9999, 3]
[7, 9999, 9999, 9999, 8, 9999, 9999]
[9999, 9, 9999, 9999, 9999, 4, 9999]
[9999, 9999, 8, 9999, 9999, 5, 4]
[9999, 9999, 9999, 4, 5, 9999, 6]
[2, 3, 9999, 9999, 4, 6, 9999]
边<B,G> 权值: 3
边<G,A> 权值: 2
边<G,E> 权值: 4
边<E,F> 权值: 5
边<F,D> 权值: 4
边<A,C> 权值: 7
如果您觉得有帮助,欢迎点赞哦 ~ 谢谢!!