最小生成树

Kruskal

 

算法和Prim算法,可以以邻接表表示的图为基础(可参考《图的表示与搜索》),并且都利用了贪心算法的思想。假设最小生成树(MST,minimum spanning tree)问题针对的是无向连通加权图G=(V, E),那么MST中边的个数为|V|-1。


Kruskal算法

首先定义几个概念。无向图G=(V, E)的一个割(S, V-S)是对V的一个划分。当一条边(u, v)∈E的一个端点属于S,而另一个端点属于V-S时,称边(u, v)通过割(S, V-S)。如果一个边的集合A中没有边通过某一割,则说该割不妨碍边集A。如果某条边的权值是通过一个割的所有边中最小的,则称该边为通过这个割的一条轻边。

         Kruskal算法首先选择权值最小的一条边,并将它的两个端点划入S,表示最小生成树的一个子集。然后,选择通过割(S, V-S)的一条轻边,将属于V-S的端点划入S。重复上述过程,直到集合V-S为空。所有被选择的边即为最小生成树的边。


 

其中,make_set运行时间为O(1),对各条边按权值进行的快速排序需要O(E lg E),执行O(E)次find_set和union_set操作所需的总时间为O(E lg E)。因此,Kruskal算法的总运行时间为O(E lg E)。

         这里,用到了不相交集合上的操作(第21章)。其中,make_set(x)建立一个新的集合,其唯一成员为x。union_set(x, y)将包含x和y的动态集合合并为一个新的集合。find_set(x)返回一个指针,指向包含x的集合的代表。在不相交集合的一种实现中,用有根树表示集合。每个结点仅指向其父结点。每棵树的根作为集合的代表,并且是它自己的父结点。为改进运行时间,可采用两种启发式策略:一是按秩合并,其思想是把包含较少结点的树的根指向包含较多结点的树的根;二是路径压缩,使查找路径上的每个结点都直接指向根结点,但不改变结点的秩。为执行路径压缩,find_set是一种两趟方法:一趟是沿查找路径上升,直到找到根;一趟是沿查找路径下降,以便更新每个结点,使之直接指向根。

  

 


--------------------------------------------------------------------------------

Prim

 

算法


Prim算法的特点是最小生成树子集A中的边总是形成单棵树。树从任意根顶点开始形成,并逐渐生成,直至该树覆盖了V中的所有顶点。在每一步,总是在以A中顶点为一个端点的所有边中,选择一条轻边加入到树中。在算法的执行过程中,不在树中的所有顶点都放在一个基于边权重的最小优先队列中(可参考《堆的使用》)。

 

 

         这里,暂且用color域标识顶点是否在优先队列中。Prim算法的性能取决于优先队列如何实现。如果用最小堆来实现,那么while循环中,执行|V|次的heap_extract_min操作需要O(V lg V)时间。另外,需要检查O(E)条边,而对边进行heap_decrease_key操作需要O(lg V)时间。因此,Prim算法的整个运行时间为O(V lg V+ E lg V)=O(E lg V)。

         附最小堆实现的最小优先队列。

  

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值