算法导论KRUSKAL算法原理及其实现

本文详细介绍了克鲁斯卡尔(Kruskal)算法的原理和实现,包括其核心思想——寻找最小权重且连接不相交子集的边,并使用并查集进行不相交集合的管理。通过排序边的权重并遍历,最终得到最小生成树。程序示例展示了如何在C++中实现这一算法,并指出在稠密图中时间复杂度主要由排序决定,为O(ElogE)。同时,文章提及了路径压缩的按秩合并方法对并查集性能的提升。
摘要由CSDN通过智能技术生成

K r u s k a l Kruskal Kruskal算法

又称作为克鲁斯卡尔算法,是基于贪心的一种最小生成树算法,根据前两部分了解到的安全边规则与不相交集合的数据结构(并查集),即可实现该算法的内容:

K r u s k a l Kruskal Kruskal方法的中心思想是在图中寻找一条权重最小的连接两个不相交集合的边即为所寻找的安全边。可以理解为找的边 ( u , v ) (u,v) (u,v)符合横向切割的轻量级边的要求且一定尊重某最小生成树集合 A A A,是否尊重节点 u u u代表的或者节点 v v v代表的某棵正在发现过程中的最小生成树集合很容易。

上述表述的是权重最小且连接两个不相交子集和,那么可以在图 G ( V , E ) G(V,E) G(V,E)展开描述为:

  • E E E中所有边按照边权从小到大排序;
  • 遍历排序后的边时进行并查集查询,判断当前边两节点是否在同一集合中;
  • 若不在同一集合中将当前边添加最小生成树中;
程序复现
class Graph
{
private:
    int V, E;
public:
    vector<pair<pair<int, int>, int>> G;
    Graph(int v, int e)
        : V(v), E(e) {}
    void add(char u, char v, int w)
    {
        add(u - 'a' + 1, v - 'a' + 1, w);
    }
    void add(int u, int v, int w)
    {
        G.push_back({{u, v}, w});
    }
    void MST_KRUSKAL();
};

以上内容为定义类型,核心代码程序为:

void Graph::MST_KRUSKAL()
{
    vector<pair<int, int>> A;
    DisjiontSet x = DisjiontSet(V);
    sort(G.begin(), G.end(), cmp);
    for (auto i : G)
        if (x.FindSet(i.first.second) != x.FindSet(i.first.first))
        {
            A.push_back({i.first.first, i.first.second});
            x.Union(i.first.first, i.first.second);
        }
}

排序过程中按照权重进行排序,其次此处不相交数据结构采用了上一节描述的路径压缩的按秩合并方法,时间复杂度 O ( ( V + E ) α ( V ) ) O((V+E)\alpha(V)) O((V+E)α(V))(合并操作+初始化节点),其中 α \alpha α函数是一个增长极慢的函数,可以近似理解为线性操作。

在图较大时,排序的时间复杂度会比并查集大的多,所以主要时间复杂度会表示在排序上,稠密图中时间复杂度表示为 O ( E l o g E ) O(ElogE) O(ElogE)

实际计算

在这里插入图片描述

按照上述样例输入后输出集合 A A A内边集合为:

h g
i c
g f
a b
c f
c d
a h
d e

注:中文书中伪代码判断是否同意集合存在异常,修改为:

if FIND-SET(u)≠FIND-SET(v)

全部代码阅读原文获取

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

数学小牛马

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值