23最小生成树之Kruskal算法

时间:2024-04-29 23:00:03

图的最优化问题:最小生成树、最短路径

典型的图应用问题

无向连通加权图的最小生成树

有向/无向加权图的最短路径

四个经典算法

Kruskal算法、Prim算法---------------最小生成树

Dijkstra算法、Floyd算法-------------最短路径

最小生成树的概念:

G=(V,E):无向连通加权图

C(e)或C(v,w): 边e=(v,w)的耗费(Cost)

若S=(V,T)是G的一棵生成树(T是树边集),那么, S的边长之和称作生成树S的耗费C(S)

耗费C(S)达到最小值的生成树S,称为G的最小耗费生成树,也称最小生成树(MinimumSpanningTree)

即C(S)≤C(S') (S'是图G的任一生成树)

注意:最小生成树可能不唯一

Kruskal算法

算法思想: 按长度从小到大的依次把边加进生成树,若添加某边后形成了回路,就舍弃这条边

反复如此,直到选出n-1条边,便得到最小生成树.。

23最小生成树之Kruskal算法

通俗来讲,该算法很简单。

步骤:

1.在空白处画出与原图一模一样的结点位置。(只画结点,权不需要,结点的位置要一模一样)。

2.按权画边。从权值最小的开始,如图,从4开始,草图就连A-B,到权值5,就连B-F,到权值6,此时就会发现,如果连接A-F,那么A-B-F就会构成一个完整的回路(从任意一点出发可以回到原点。)。因此,就要舍去权值6,即边A-F不可连接。。。。。依次按权大小画其他边。直到最后一个结点。

Kruskal算法伪程序形式

void  Kruskal(***) //***表示函数要求的参数

{  int et=0;           //et用于记录选中的边数

置树边集T为空;

while(et<n-1)               //n是图中的顶点数

{ 从G中选出当前最短边(v,w);

if(添此边于T中,不使生成树产生回路)

{ 把(v,w)加进T;et++;}

else  舍弃(v,w);

}

}

实现方法分析:

23最小生成树之Kruskal算法

23最小生成树之Kruskal算法

23最小生成树之Kruskal算法

23最小生成树之Kruskal算法

子树合并法描述和示例

23最小生成树之Kruskal算法

描述:

23最小生成树之Kruskal算法

23最小生成树之Kruskal算法

23最小生成树之Kruskal算法

Kruskal算法的子树合并法描述形式:

方法一:

void  Kruskal(***) //***表示函数要求的参数

{  int et=0;

每个顶点自成一个集合,并指定集合名;

while(et<n-1)

{ 从G中选出当前最短边(v,w);

找到v所在的集合名i,和w所在的集合名j;

if(i!=j)

{  把(v,w)加进T;  et++;

将集合i与集合j合并成一个集合k;     }

}

}

方法二:

void  Kruskal(***) //***表示函数要求的参数

{  int et=0;

每个顶点一个集合,并指定集合名 ;

while(et<n-1)

{ 从G中选出当前最短边(v,w);

if(v和w不在同一子树中)

{ 把(v,w)加进T;et++;

将v所在的子树与w所在的子树合并成一棵子树;

}

}

}

结论:无论是按权画边法,还是子树合并法都是可以找出最小生成树,但是个人认为按权画边法比较容易理解。