Prim算法
1).输入:一个加权连通图,其中顶点集合为V,边集合为E;
2).初始化:U = {x},其中x为集合V中的任一节点(起始点),E = {}为空;
3).重复下列操作,直到U = V:
a.在集合E中选取权值最小的边 <u, v>
,其中u为集合U中的元 素,而v不在U集合当中,并且v∈V(如果存在有多条满足前述条件即具有相同权值的边,则可任意选取其中之一);
b.将v加入集合U中,将<u, v>
边加入集合E中;
4).输出:使用集合U和E来描述所得到的最小生成树。
算法简单实现
/**
* Created by 默默 on 2018/3/22.
*/
public class Graph {
public static int INF = Integer.MAX_VALUE;
/**
* (v0)-2-(v1)
* / \ / \
* 4 1 3 10
* / \ / \
* (v2)-2- (v3)-7- (v4)
* \ / \ /
* 5 8 4 6
* \ / \ /
* (v5) -1- (v6)
*/
@org.junit.Test
public void testPrim() {
int[][] adj = {
{0, 2, 4, 1, INF, INF, INF},
{2, 0, INF, 3, 10, INF, INF},
{4, INF, 0, 2, INF, 5, INF},
{1, 3, 2, 0, 7, 8, 4},
{INF, 10, INF, 7, 0, INF, 6},
{INF, INF, 5, 8, INF, 0, 1},
{INF, INF, INF, 4, 6, 1, 0},
};
System.out.println("总长=" + prim(adj));
/** (v0)-2-(v1)
* \
* 1
* \
* (v2)-2- (v3) (v4)
* \ /
* 4 6
* \ /
* (v5) -1- (v6)
*/
}
public int prim(int[][] adjMatrix) {
//节点数
int count = adjMatrix[0].length;
//初始节点定为0
int cur = 0;
//dist[index]表示 节点index 到 集合U 的最小距离
int[] dist = new int[count];
//集合U初始化只包含初始节点
for (int i = 0; i < count; i++) {
dist[i] = adjMatrix[cur][i];
}
boolean[] visit = new boolean[count];
visit[cur] = true;
System.out.println("vertex->" + cur);
int sum = 0;
for (int i = 1; i < count; i++) {//找节点的次数
int nearBy = 0;
int dis = INF;
//每次找距 集合U 距离最短的未访问节点
for (int j = 0; j < count; j++) {
if (!visit[j] && dist[j] < dis) {
nearBy = j;
dis = dist[j];
}
}
sum += dis;
visit[nearBy] = true;
System.out.println("vertex->" + nearBy);
//更新其他未访问节点到集合U的距离(集合U增加了nearBy节点)
for (int j = 0; j < count; j++) {
if (!visit[j] && dist[j] > adjMatrix[nearBy][j]) {
dist[j] = adjMatrix[nearBy][j];
}
}
}
return sum;
}
}