「这是我参与2022首次更文挑战的第22天,活动详情查看:2022首次更文挑战」。
Kuskal算法
Kruskal算法——基本思想
Prim算法的关键是什么?
找到连接 U 和 V-U 的最短边
Prim算法:先构造满足条件的候选最短边集,再查找最短边
Kruskal算法:先查找最短边,再判断是否满足条件
Kruskal算法——基本思想
算法:Kruskal算法
输入:无向连通网G=(V,E)
输出:最小生成树T=(U,TE)
1. 初始化:U=V;TE={ };
2. 重复下述操作直到所有顶点位于一个连通分量:
2.1 在E中选取最短边(u,v);
2.2 如果顶点 u、v 位于两个连通分量,则
2.2.1 将边 (u,v) 并入TE;
2.2.2 将这两个连通分量合成一个连通分量;
2.3 在 E 中标记边 (u,v),使得 (u,v) 不参加后续最短边的选取;
Kruskal算法——存储结构
图采用什么存储结构呢?
边集数组表示法
如何存储连通分量呢?
并查集 并查集:集合中的元素组织成树的形式:
查找两个元素是否属于同一集合:所在树的根结点是否相同
合并两个集合——将一个集合的根结点作为另一个集合根结点的孩子
如何判断两个顶点是否位于同一个连通分量及合并连通分量呢?
int FindRoot(int parent[ ], int v){
int t = v;
while (parent[t] > -1)
t = parent[t];
return t;
}
vex1 = FindRoot(parent, i);
vex2 = FindRoot(parent, j);
if (vex1 != vex2) {
parent[vex2] = vex1;
}
Kuskal算法代码实现
void Kruskal(EdgeGraph *G){
int i, num = 0, vex1, vex2;
for (i = 0; i < G->vertexNum; i++)
parent[vertexNum] = -1;
for (num = 0, i = 0; num < G->vertexNum; i++){
vex1 = FindRoot(parent, G->edge[i].from);
vex2 = FindRoot(parent, G->edge[i].to);
if (vex1 != vex2) {
printf("(%d, %d)%d ", G->edge[i].from, G->edge[i].to, G->edge[i].weight);
parent[vex2] = vex1;
num++;
}
}
}