📌  相关文章
📜  MST的Prim和Kruskal算法之间的区别(1)

📅  最后修改于: 2023-12-03 14:44:25.441000             🧑  作者: Mango

MST的Prim和Kruskal算法之间的区别

最小生成树(Minimum Spanning Tree, MST)是用于在一个加权无向连通图中构造一棵生成树,使树的所有边的权值之和最小的树。MST问题是一个经典的图论问题,在实际中有着广泛的应用。Prim算法和Kruskal算法是两种常用的MST算法,它们的实现思路和效率不同,下面我们来简单介绍一下它们的区别。

Prim算法

Prim算法也叫做贪心算法,它以一个节点为起点开始,每次找到离该节点最短的边所对应的点,并将该点加入MST中。然后以新加入的点为起点,重复以上过程直到构造成功。

Prim算法的时间复杂度是O(n^2),其中n表示节点个数。Prim算法的优点是对于稠密图表现较好,复杂度不会太高,同时它能够输出每个节点在MST中的父亲结点,非常适合在求最短路径时使用。

以下是Prim算法的C++代码。

const int INF = 0x3f3f3f3f;

int prim(int n, int **G, int start) {
    int *D = new int[n];
    bool *flag = new bool[n];
    int sum = 0;
    for (int i=0; i<n; i++) {
        D[i] = INF;
        flag[i] = false;
    }
    D[start] = 0;
    for (int i=0; i<n; i++) {
        int min_v = INF, u;
        for (int j=0; j<n; j++) {
            if (!flag[j] && D[j] < min_v) {
                u = j;
                min_v = D[j];
            }
        }
        flag[u] = true;
        sum += min_v;
        for (int j=0; j<n; j++) {
            if (!flag[j] && G[u][j] < D[j]) {
                D[j] = G[u][j];
            }
        }
    }
    delete[] D;
    delete[] flag;
    return sum;
}
Kruskal算法

Kruskal算法也是贪心算法的一种,它的实现是将所有的边按照权值从小到大排序,依次取出最小权值的边,如果这条边连接的两个端点在同一集合内,则不需要加入最小生成树中,否则加入最小生成树中,直到选取n-1条边为止。

Kruskal算法的时间复杂度是O(m logm),其中m表示边的数量。Kruskal算法的优点是对于稀疏图表现较好,同时它不需要遍历所有的节点,只需要遍历所有的边,对于大规模的图表现更为优秀。

以下是Kruskal算法的C++代码。

const int MAX_N = 10000;
const int MAX_M = 100000;
struct Edge {
    int u, v, w;
} edges[MAX_M];
int parent[MAX_N];
int rank[MAX_N];

void make_set() {
    for (int i=0; i<MAX_N; i++) {
        parent[i] = i;
        rank[i] = 0;
    }
}

int find_set(int x) {
    if (parent[x] != x) {
        parent[x] = find_set(parent[x]);
    }
    return parent[x];
}

void union_set(int x, int y) {
    int px = find_set(x);
    int py = find_set(y);
    if (px == py) {
        return;
    }
    if (rank[px] > rank[py]) {
        parent[py] = px;
    } else {
        parent[px] = py;
        if (rank[px] == rank[py]) {
            rank[py]++;
        }
    }
}

bool cmp(Edge a, Edge b) {
    return a.w < b.w;
}

int kruskal(int n, int m, Edge *edges) {
    make_set();
    sort(edges, edges+m, cmp);
    int sum = 0, cnt = 0;
    for (int i=0; i<m; i++) {
        int u = edges[i].u;
        int v = edges[i].v;
        int w = edges[i].w;
        if (find_set(u) == find_set(v)) {
            continue;
        }
        union_set(u, v);
        sum += w;
        cnt++;
        if (cnt == n-1) {
            break;
        }
    }
    return sum;
}
总结

Prim算法与Kruskal算法都是MST算法的代表,它们在实现思路上略有不同,适用于不同类型的图。在实际应用中,根据具体的需求和数据特点,选择不同的MST算法可以使算法表现更加出色。