最小生成树算法 -- Prim算法与Kruskal算法

1、什么是最小生成树

(1)是一棵树

  • 无回路
  • |v| 个顶点一定有 |v| - 1条边

(2)是生成树

  • 包含全部顶点
  • |v| - 1条边都在图里

(3)边的权重和最小

2、Prim算法 – 让一棵小树长大

Prim算法其实就是改进的dijkstra算法。Prim算法是先选择一个点作为源点,然后根据其它点到源点s的最小距离,逐步收录其它顶点。收录的过程是按照顶点来进行收录的。

/*
    Prim算法 -- 让一个小树长大,逐步收录每一条最小边
*/

void Prim() {
    MTS = {s}; // 随便选择一个点作为源点s,然后收录
    while (1) {
        v = 未收录顶点中的最小值;
        if (v不存在) {
            break;
        }
        将v收录进MTS中,dist[v] = 0;
        for (v的每个邻接点w) {
            if (dist[w] != 0) {
                if (dist[w] > edge[w][v]) {
                    dist[w] = edge[w][v];
                    parent[w] = v;  // 表示在生成树中,w连接到节点v
                }
            }
        }
    }
    if (MTS中收录的顶点个数小于|v|) {
        cout << "生成树不存在\n";
    }
}

2、Kruskal算法 – 将森林合并成树

与Prim算法不同的是,Kruskal算法每次选择的都是边,每次将权重最小的边加入,如果不构成回路,那么就认为是一条有效边。最终判断有效边的数量是否为|v| - 1。

void Kruskal(Graph G) {
    MTS = {};
    while (MTS中不到|v| - 1条边 && E中还有边) {
        从E中选择一条权重最小的边E(v,w);    // 可以利用最小堆E(v, w)从E中删除;
        if (E(v, w)不在MTS中构成回路)       // 回路判断:并查集
        {E(v,w)加入到MTS;
        }
    }
    if (MTS中不到 |v| - 1条边) {
        cout << "生成树不存在\n";
    }
}

你可能感兴趣的:(算法与数据结构,算法,图论,Prim算法,Kruskal算法,最小生成树)