Kruskal算法

简介: Kruskal算法

介绍

Kruskal算法是一种最小生成树算法,用于在带有权重的连通图中找到最小生成树。一个连通图由一组节点和连接这些节点的边组成,每条边都有一个权重。

Kruskal算法的基本思想是:

从边的权重从小到大进行排序,然后依次考虑每条边。在考虑每条边时,判断当前的边是否会形成环路,如果不会形成环路,则将该边加入最小生成树的边集合中。

具体算法步骤如下:

1. 初始化一个空的最小生成树边集合。

2. 将所有边按照权重从小到大排序。

3. 依次考虑每条边,判断当前边的两个端点是否已经在最小生成树的边集合中,如果不在则将该边加入最小生成树的边集合中。

4. 继续下一条边的考虑,直到最小生成树的边数达到节点数减1或者所有边都考虑完毕。

Kruskal算法的时间复杂度主要取决于对边进行排序的部分,通常使用的排序算法是快速排序或者归并排序,时间复杂度为O(ElogE),其中E为边的数量。

总结一下,Kruskal算法以贪心的方式逐步构建最小生成树,它的优点在于简单易懂且实现相对容易,适用于边稀疏的图。

举例

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// 边的结构体
struct Edge {
    int src, dest, weight;
};
// 并查集的数据结构
struct DisjointSet {
    vector<int> parent;
    void init(int n) {
        parent.resize(n);
        for (int i = 0; i < n; i++) {
            parent[i] = i;
        }
    }
    int find(int x) {
        if (parent[x] != x) {
            parent[x] = find(parent[x]);
        }
        return parent[x];
    }
    void merge(int x, int y) {
        int rootX = find(x);
        int rootY = find(y);
        parent[rootX] = rootY;
    }
};
bool compareEdges(Edge& edge1, Edge& edge2) {
    return edge1.weight < edge2.weight;
}
void kruskal(vector<Edge>& edges, int n) {
    sort(edges.begin(), edges.end(), compareEdges);
    DisjointSet ds;
    ds.init(n);
    vector<Edge> minimumSpanningTree;
    int edgeCount = 0;
    int i = 0;
    while (edgeCount < n - 1 && i < edges.size()) {
        Edge& currentEdge = edges[i];
        int srcParent = ds.find(currentEdge.src);
        int destParent = ds.find(currentEdge.dest);
        if (srcParent != destParent) {
            minimumSpanningTree.push_back(currentEdge);
            ds.merge(srcParent, destParent);
            edgeCount++;
        }
        i++;
    }
    cout << "边\t权重\n";
    for (const auto& edge : minimumSpanningTree) {
        cout << edge.src << " - " << edge.dest << "\t" << edge.weight << "\n";
    }
}
int main() {
    int n, m;
    cout << "输入节点数:";
    cin >> n;
    cout << "输入边数:";
    cin >> m;
    vector<Edge> edges(m);
    cout << "输入每条边的起点、终点和权重:\n";
    for (int i = 0; i < m; i++) {
        cin >> edges[i].src >> edges[i].dest >> edges[i].weight;
    }
    kruskal(edges, n);
    return 0;
}

这个例子中,首先定义了边的结构体Edge,然后定义了并查集的数据结构DisjointSet,并实现了并查集的初始化、查找和合并操作。接下来,通过比较边权重的函数compareEdges来对边进行排序。然后,在kruskal函数中,先对边进行排序,然后使用并查集来判断边的两个端点是否在同一个连通分量中,如果不在,则将边加入最小生成树中,并合并这两个端点为同一个连通分量。最后,输出最小生成树的边和权重。

main函数中,首先读取节点数和边数,然后逐个读取每条边的起点、终点和权重。最后调用kruskal函数来计算最小生成树。


相关文章
|
5月前
|
算法 C++
用prim和kruskal算法求最小生成树问题
用prim和kruskal算法求最小生成树问题
47 0
|
8月前
|
存储 算法 C++
最小生成树问题及Kruskal算法的解析
最小生成树问题及Kruskal算法的解析
73 2
|
10月前
|
算法 Java
数据结构(13)最小生成树JAVA版:prim算法、kruskal算法
13.1.概述 最小生成树,包含图的所有顶点的一棵树,树的边采用包含在图中的原有边中权重和最小的边。翻译成人话就是遍历一遍全图所有顶点的最短路径,这条路径就叫最小生成树。 最小生成树存在和图是连通图互为充要条件,顶点都不连通,肯定不可能有路能遍历一遍全图。 求解最小生成树有两种常用算法:
108 0
|
10月前
|
算法 Java 内存技术
Kruskal算法求最小生成树 Java带输入输出
Kruskal算法求最小生成树 Java带输入输出
74 0
|
10月前
|
算法
Prim算法和Kruskal算法到底哪个好?
Prim算法和Kruskal算法到底哪个好?
136 0
|
10月前
|
算法
LeetCode算法小抄 -- Kruskal 最小生成树算法
LeetCode算法小抄 -- Kruskal 最小生成树算法
|
11月前
|
算法
大话数据结构--Kruskal算法
大话数据结构--Kruskal算法
63 0
|
11月前
|
算法 内存技术
搜索与图论-最小生成树(Prim 算法和 Kruskal 算法)
搜索与图论-最小生成树(Prim 算法和 Kruskal 算法)
kruskal算法的实现
kruskal算法的实现
|
算法 C语言
最小生成树——Prim算法与Kruskal算法
最小生成树——Prim算法与Kruskal算法
306 0
最小生成树——Prim算法与Kruskal算法