Kuskal算法

109 阅读2分钟

「这是我参与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算法——存储结构

图采用什么存储结构呢?

边集数组表示法

image.png

image.png

image.png

如何存储连通分量呢?

并查集 并查集:集合中的元素组织成树的形式:
查找两个元素是否属于同一集合:所在树的根结点是否相同
合并两个集合——将一个集合的根结点作为另一个集合根结点的孩子

image.png

如何判断两个顶点是否位于同一个连通分量及合并连通分量呢?

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++;
        }
     }
}