最小生成树——Kruskal算法

啦啦啦~~~笔者又回来了。今天给诸位带来的是这段时间笔者在coursera上面跟着北大的老师学离散的时候学到的最小生成树里面的一种叫Kruskal算法,除此以外还有Prim算法(但是笔者还没有弄懂)

首先理清几个离散数学上面的几个概念

①连通图:在无向图中,若任意两个点和都有路径相通,则称该无向图为连通图

②赋权图:每条边都有一个非负实数对应的图。这个实数称为这条边的权。

③生成子图:设G=<V,E>,G’=<V’,E’>是两个图,若V’V,E’E,则称GG的子图,GG的母图,记作G’G.G’GV’=V,则称GG的生成子图

④生成树:一个连通图的生成树是指一个连通子图,它含有图中全部n个顶点,且又n-1条边构成一棵树

⑤最小生成树:在赋权图中,使得最终权值最小的生成树被称为最小生成树

接下来介绍Kruskal算法的中心思想

Kruskal算法的中心思想就是每次取权尽可能小的边,只要它与已取的边不构成回路,直到取得一棵生成树为止,这也叫避圈法。

然后就是介绍Kruskal算法的操作步骤:
输入:n阶无向连通带权图G=<V,E,W>,其中E=<e1,e2,e3,....em>

输出:G的最小生成树T

(1)按权从小到大排列边,不妨设W(e1)W(e2)....W(em)

(2)T←Øi←1,k←0.

(3)eiT中的边不构成回路,则令T←T{e1},k←k+1/若条件成立,则取ei,否则弃去ei

(4)k<n-1,则令i←i+1,转(3.

如图就是一个最小生成树的示例


下面是代码展示

这个算法的主要难点就是如何去判断回路

在参考了其他博主的代码后,发现有很多是应用了指针来实现的,如下

int Find(int *parent,int f)
 { 
while(parnet[f]>0) f = parent[f] 
return f; 
}

下面就是完整的代码展示

int Find(int *parent,int f)
{
    while(parnet[f]>0)
        f = parent[f]
    return f;
}

Typedef struct
{
    int begin;
    int end;
    int weight;
}Edge;

void Kruskal(MGraph g)
{
    Edge E[MaxSize];
    int vset[MaxSize];
    int i,k,j;
    for(i=0;i<g.n;i++)
        for(j=0;j<g.n;j++)
            if(g.edges[i][j]!=0 && g.edges[i][j]!=INF)
            {
                E[k].begin = i;
                E[k].end = j;
                E[k].weight = g.edges[i][j];
                k++;
            }
    InsertSort(E,g.e);//排序
    for(i=0;i<g.n;i++) vset[i]=0;
    //要区n-1条边出来 
    k = 1;
    //每次取出一条边,所以要有一个元素记住现在取到第几条边了 
    j = 0;
    while(k<g.n)
    {
        u1 = E[j].begin;
        u2 = E[j].end;
        sn1 = Find(vset,u1);
        sn2 = Find(vset,u2);
        if(sn1!=sn2)
        {
            vset[sn2] = sn1;
            printf();
            k++;
        }
        j++;
    }
}

P.S.文章中所有离散数学概念来自清华大学出版社屈婉玲等人编著的《离散数学》第五版,代码来自博客http://blog.csdn.net/qq122627018/article/details/51912324

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值