Prim算法和Kruskal算法

Prim算法和Kruskal算法两种算法的目的都是产生最小生成树那什么是最小生成树呢

1.最小生成树

简而言之,一个连通图的生成树是一个极小的连通子图,它有以下特称:
(1):包含图中全部顶点
(2):只有构成一棵树的n-1条边(就像5个点只需要4条边就可以连接)
最小生成树便是图中所有生成树中权值和最小的树。

2.Prim算法:

知道了最小生成树的定义,我们再来看看Prim算法,代码如下:

在这里插入图片描述
第42行,传入的G是已经生成好的邻接矩阵,i则是开始的顶点(事实上,不论从哪一个点开始,对结果是没有影响的)
数组Lowcost的作用是存储当前顶点所连接的边的最小值,
数组Clost用于存储顶点所连接的边。例如:Clost[j]=k是值lowcost的第j条边连接的是顶点k

第47到51行,进行两个数组的初始化,初始值为顶点i所连接的边的权值,已经顶点i
(第53行,for循环从1开始,是因为创建图中,也是从1开始写入)

57到66行在Lowcost中循环出最小的权值,将该边连接的顶点传给k,(注意:min初始值不能为lowcost[0],因为图中对角线的值为0,会导致程序的错误).
Lowcost[k]=0的作用是将已被调用的边归为0,防止再调用.

第70到78行,将k的那个点与lowcost进行比较,留下权值较小的一个,就是把G.arc[i][j]与G.arc[k][j]的权值进行比较,这样,每加入一个顶点,Lowcost数组存储的便是已加入顶点中权值最小那一个,当进行n-1次循环,便可生成"最小生成树".
这便是prim算法.

3.Kruskal算法

kruskal算法的是将所有的边按照权值递增的顺序排序,如果没有形成闭合回路,便采用该边.和prim算法不同的是,Kruskal算法是按一定的顺序访问权值,prim则是每一次都要遍历,所以prim采用后,需要将权值赋值为0,而Kruskal不用,
下图为快速排序算法:
在这里插入图片描述

如何判断选取的边是否构成了回路呢?我采取了树的方式:

在这里插入图片描述

树的双亲在一开始是指向自己的,表明没有点进行连接,如果有边被调用,便会调用UNION函数,
该函数有三种情况:
(1):两个点中一个的rank大于另一个点的rank,rank大,表明该点深度低,该点应该作为另一个点的双亲.
(2):如果rank相等,表明两个顶点之前都没有双亲,此时便选用后面的一个点作为前面一个点的双亲.
(3)y点rank大,则选择y为x的双亲.
这样,经过该函数,任何被调用的边如果相连,便会有一个相同的双亲.而在上图中,只要双亲不同,便可调用该边,就避免了环路的产生.
在这里插入图片描述
下图是一个寻找双亲的过程,其最终的目的,是找到x的最初顶点.
举例:
假设x=1,寻找顶点1的双亲的过程就是寻找之前被采用的边是否有与顶点1相连,如果有就去继续寻找与该点相连的点.到最后,找到一个点,双亲是它本身,便是这个路径的起点.
在这里插入图片描述
主函数中,cout和j的作用是不相同的,cout的作用是确保有G.i-1条边,这样才可以保证边能够把所有的顶点相连.
而j的主要作用是查询排序好的E[MAX]数组,如果有形成回路的边,k便保持原值,j+1,表示访问下一条边.
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值