Prim算法和Kruskal算法构造最小生成树

最小生成树

首先,生成树是建立在无向图中的,对于有向图,则没有生成树的概念,所以接下来讨论的图均默认为无向图。对于一个有n个点的图,最少需要n-1条边使得这n个点联通,由这n-1条边组成的子图则称为原图的生成树。一般来说,一个图的生成树并不是唯一的(除非原图本身就是一棵树)。
现在考虑带权图G,即图的边带权,则最小生成树就是在G中权值和最小的一颗生成树,显然最小生成树也不是唯一的,但是其权值唯一。有很多应用需要用到最小生成树的概念,比较直观的一个应用就是:有n个村庄,现在要在这些村庄之间修一些路,其中村庄i和村庄j之间的距离是Dij,现在要修最短的路使得所有村庄连接起来。

Kruskal算法(考虑边)

Kruskal算法同样是基于贪心策略,但是它和Prim算法不同的是,在算法过程中它并不维护一个连通的分量,而是将多个连通分量合并到一起得到一颗生成树。个人觉得Kruskal算法的思想比它算法本身要重要,能够解决很多其他问题。

算法的思想:对于n个点先把图中各边的大小按照权值由小到大的顺序排列起来。最开始各个点都是独立的,先选一个权值最小的边连起来,然后选一个次小的边权值,依次类退,直到选够n-1条边即可,条件这些边不能构成圈。

算法的证明:如果一直没有构成圈,即是每条边都是按照最小,次小的顺序,这样的话,这n-1条边的权值之和肯定可以达到最小,毋庸置疑贪婪算法绝对可保证最优解,然而他可能加边的时候可能构成圈,这是按照kruskal算法,就必须把这个边去掉,换比这个边次小的边,那么就不能保证完全的贪婪。所以有必要证明。

设T是任意一个生成树(核心:选边)。

T1是由kruskal 算法得到的边

先考虑T和T1由1条边不一样:(很重要)

T1:e i1,e i2 ,e i3,   e ik------e in-1;

T  :  ---------

e ik是第一个与T不一样的边的。

那么T肯定多了一条没在T1中的边记为e’;

既然是第一个不一样的,如果(e'大于等于e ik),自然T>T1;如果e'在(ei3到eik之间),因为T没选e',所以推理,e1,e2,e3,e'回构成圈。所以T中不可能出现这样的e',因为如果出现,又由于是第一个不一样的边,这意味着ei1,ei2,ei3都在T1中,会出现圈,所以不可能。

在依次考虑两条边不一样:

将一条边作为一个桥梁,即可得到。

缺点:在写程序时,要判断是否会构成圈,但很难写。所以出现了适合写程序的prim算法;

prim算法

Prim算法基于一种贪心的思想,通过局部最优策略,每次将一条边加入所构建的生成树中,加完n-1条边后,保证最后所得的生成树是整体最优的,即最小生成树。

算法思想:先找一个权值最小的边,然后以这两个边的端点,寻找所有与之相连的边,找权值最小,然后以这三个点为端点在找与之相连的最小的权值的边,不断加进来,直到加完n-1条边为止。

加边时,可把前面的边和点看成一个树,树的内部是不能连线(加边),可以缩成一个点,加边相当于树的生长,在外部加边。也是一种贪婪算法。

他避免了圈的形成。

你可能感兴趣的:(2015数学建模)