所谓最小生成树,就是一个图的极小连通子图,它包含原图的所有顶点,并且所有边的权值之和尽可能的小,不需要形成环路。
最小生成树可能不为一,但权值一定相等
package com.neusoft.data.structure;
import java.util.*;
/**
* Prim算法实现最小生成树(从带权图找最小生成树)
* 所谓最小生成树,就是一个图的极小连通子图,它包含原图的所有顶点,并且所有边的权值之和尽可能的小,不需要形成环路。
* 最小生成树由一维数组表示
* 程序输出结果分析:
* [-1, 0, 0, 1, 2] 代表父节点
* 0, 1,2,3,4 图的顶点数字
* 0 -1 说明是根节点
* 1 0 0 是1的父节点
* 2 0 0 是2的父节点
* 3 1 1是3的父节点
* 4 2 2是4的父节点
*
* 从已触达所有顶点出发,寻找到达新顶点的权值最小的边。一直到所有顶点连通。
*
* INF:表示没有连通 0-----3没有线路连接
*/
class PrimTest {
final static int INF = Integer.MAX_VALUE;
public static int[] prim(int[][] matrix) {
List<Integer> reachedVertexList = new ArrayList<Integer>();
//选择顶点0为初始顶点,放入已触达顶点集合中
reachedVertexList.add(0);
//创建最小生成树数组,首元素设为-1
int[] parents = new int[matrix.length];
parents[0] = -1;
//边的权重
int weight;
//源顶点下标
int fromIndex = 0;
//目标顶点下标
int toIndex = 0;
while (reachedVertexList.size() < matrix.length) {
weight = INF;
//在已触达的顶点中,寻找到达新顶点的最短边
for (Integer vertexIndex : reachedVertexList) {
for (int i = 0; i < matrix.length; i++) {
if (!reachedVertexList.contains(i)) {
if (matrix[vertexIndex][i] < weight) {
fromIndex = vertexIndex;
toIndex = i;
weight = matrix[vertexIndex][i];
}
}
}
}
//确定了权值最小的目标顶点,放入已触达顶点集合
reachedVertexList.add(toIndex);
//放入最小生成树的数组
parents[toIndex] = fromIndex;
}
return parents;
}
public static void main(String[] args) {
int[][] matrix = new int[][]{
{0, 4, 3, INF, INF},
{4, 0, 8, 7, INF},
{3, 8, 0, INF, 1},
{INF, 7, INF, 0, 9},
{INF, INF, 1, 9, 0},
};
int[] parents = prim(matrix);
System.out.println(Arrays.toString(parents));
}
}
输出:
[-1, 0, 0, 1, 2]
从带权图找最小生成树:
![8308c1aa580fccab800fe63bbc6dc22b.png](https://i-blog.csdnimg.cn/blog_migrate/13b1acc48ee4e5c5f668b8c872d6e6b7.jpeg)
生成的最小生成树(手绘):
0
/
1 2
/
3 4