Kruskal最小生成树

本文详细介绍了Kruskal算法如何利用并查集数据结构实现,通过一系列实例演示了如何判断连通性、合并集合以及计算最小生成树的过程。从初始化每个顶点的集合到最终找到最小权重边连接节点,适合理解并查集在图论中的应用。
摘要由CSDN通过智能技术生成

Kruskal最小生成树的简单实现

思路:

每次选择权值最小的边,使这条边两个顶点相互连通(如果两个顶点已经连通,则跳过)

直到所有顶点全部连通

判断两个顶点是否连通,需要用到并查集

一个集合有一个代表人,可以把集合看成一个家庭,代表人就是顶梁柱(root)

  • 初始化:每个顶点,在只有自己的集合,这个集合代表人初始化为自己

  • 并:如果两个顶点分别所在集合的代表人不相同,则合并

    • a集合代表人认b集合代表人为老大,则a集合的其他顶点也认b集合代表人为老大
  • 查:找到某个顶点所在集合的代表人

例如

  1. 初始化,有六个集合,分别是{v0},{v1},{v2},{v3},{v4},{v5},代表人分别是自己
  2. v0与v3的代表人不一样,则把v0,v3连通,合并到一个集合,认v3为代表人
    1. {v0},{v3} -> {v0,v3}(代表v3)
  3. 同理连通v1,v4,合并{v1},{v4} -> {v1,v4}(代表v4)
  4. 同理连通v2,v5,合并{v2},{v5} -> {v2,v5}(代表v5)
  5. v2,v3所在集合代表不一样,所以连通v2,v3,合并成{v0,v3,v2,v5}(代表v3)
  6. v3,v5所在集合代表都是v3,所以跳过
  7. 其他同理

image-20210430145925570

并查集简单实现(UnionAndFind.h)

#include <iostream>
#include <queue>
using namespace std;
#define VexSum 10
#define MaxSize 6
int root[MaxSize];
//初始化根为自己
bool InitRoot()
{
    for (int i = 0; i < MaxSize; i++)
    {
        root[i] = i;
    }
    return true;
}
int FindRoot(int n)
{
    //如果根为自己
    if (root[n] == n)
    {
        return n;
    }
    else
    {
        //递归找到自己的根
        return FindRoot(root[n]);
    }
}
bool Union(int a, int b)
{
    //如果a的根为b的根,这说明a,b已连通
    if (FindRoot(a) == FindRoot(b))
    {
        return true;
    }
    else
    {
        //a认b为爸爸
        root[FindRoot(a)] = FindRoot(b);
        return false;
    }
}

Kruskal算法(Kruskal.cpp)

使用queue队列模块实现

#include "UnionAndFind.h"
typedef struct Vex
{
    int v1, v2;
    int weight;
} Vex;
typedef struct Kruskal
{
    int MinWeight;
    queue<Vex> q;
} Kruskal;
//初始化
bool Init(Kruskal &k)
{
    //初始化root数组
    InitRoot();
    //创建队列
    for (int i = 0; i < VexSum; i++)
    {
        Vex v;
        cin >> v.weight >> v.v1 >> v.v2;
        k.q.push(v);
    }
    //初始化最小生成树权值之和
    k.MinWeight = 0;
    return true;
}
bool KruskalFunction(Kruskal &k)
{
    while (!k.q.empty())
    {
        //如果两点连通
        if (Union(k.q.front().v1, k.q.front().v2))
        {
            printf("%d与%d已连通,所以跳过!\n", k.q.front().v1, k.q.front().v2);
        }
        else
        {
            printf("%d与%d还没有连通,所以连通!\n", k.q.front().v1, k.q.front().v2);
            k.MinWeight += k.q.front().weight;
        }
        k.q.pop();
    }
    printf("最小生成树权值之和为:%d\n", k.MinWeight);
    return true;
}
int main()
{
    /*
1 0 3
2 2 5
3 1 4
4 2 3
4 3 5
5 0 2
5 1 3
6 0 1
6 3 4
6 4 5
*/
    Kruskal k;
    Init(k);
    KruskalFunction(k);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值