最小生成树(kruskal算法和Prim算法)

1.问题

最小生成树:一个有 n 个结点连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边。

2.解析

prim算法:
**核心思想:**让一颗小树长大。
①随机选择一点v加入V(初始时为空),并设一变量ans记录已选中的权值和
②找到图中权值最小的边<v1,v2>,要求v1存在V中、v2不存在V中
③将v2加入V中,ans += 边<v1,v2>的权重
重复②③步骤
遇到的难点:
for(已选的点){
for(未选的点){
找出权值最小的边
}
将该边的权值加入总权重中
将找到的点置为已选中
}//错误思路
后来我发现这样做是行不通的,因为每加入一个新的点,都需要再重新
走一遍上面的代码,也就是说我设计的算法的时间复杂度不是O(n^2)
而是O(n^3)。
算法关键的一点是如何记录已经扫描过的边,比如我从v1开始,,经历步骤②③后将v2加入了V,
如果不做处理,步骤②又会先从v1开始扫描再扫描v2,这就会增大时间复杂度。
解决:
用三个数组并且不断更新这三个数组直到找出最小生成树
selected:记录某个顶点是否已加入生成树
T:是,F:否,初始状态下所有顶点为F。
minDist:联结已选顶点集合到未选顶点的所有边中最短的那条边
初始状态下均为inf。
parent:以selected的元素为v1,minDist的元素为边,确定parent数组的值,即parent存放的是v2。
初始状态下均为-1

图片演示
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

结束条件
①所有顶点都为T
②选择的边数 = 顶点数 - 1

kruskal算法:
**核心思想:**将森林合并成树
将所有边的权值按从小到大的顺序排列,若边的两顶点与选中的顶点没有构成回路,则将这两个顶点加入已选顶点中,若构成回路则跳过该边,直到所有顶点都被选中。

图片演示
在这里插入图片描述

3.设计

int prim()
{
随机选一个起点v,将该点的selected置为T
while(1)
{
for(v的每个未被收录的每个邻接点)
{
更新minDist和parent数组
}
for(v的每个未被收录的每个邻接点)
{
找出未收录顶点中dist最小的顶点u
}
置selected[u]为T
置v=u
if(全部顶点都已被收录)break;
}
}

void kruskal()
{
MST为空
while(MST中边数<|V|-1 && E不为空)
{
选取E中权重最小的边e
将e从E中删除
if(e在MST中不构成回路)将e加入MST
}
}

4.分析

prim算法:O(n^2)
kruskal算法:O(eloge)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值