数据结构—— 最小生成树连通网的两种算法区别和用法【普里姆(Prim)算法-克鲁斯卡尔(Kruskal)算法】

目录:

一:最小生成树(Minimum Cost Spanning Tree)

1.定义

成本最小

2.图形化分析

3.分析

二:普里姆算法(Prim算法)

1.定义

2.算法步骤

3.算法简单描写叙述

A:输入:

B:初始化:

C:反复下列操作,直到Vnew = V:

D:输出:

4.图例描写叙述

5.普利姆(Prim)算法适用于求解无向图中的最小生成树

6.简单证明prim算法

7.算法代码实现(未检验)

8.时间复杂度

三:克鲁斯卡尔(Kruskal)算法

1.定义

2.算法步骤

3.算法简单描写叙述

A:记Graph中有v个顶点

B:新建图Graphnew

C:将原图Graph中全部e个边按权值从小到大排序

D:循环:

4.图例描写叙述

5.Kruskal算法构造最小生成树的过程图解 

6.简单证明Kruskal算法

A:归纳基础:

B:归纳过程:

7.算法代码实现(未检验)

8.时间复杂度

四:对比


一:最小生成树(Minimum Cost Spanning Tree)

1.定义

构造连通网最小代价生成树称为 最小生成树

 

成本最小

就是顶点

条边把一个连通图连接起来

并且使权值的和最小

 

2.图形化分析

数据结构—— 最小生成树连通网的两种算法区别和用法【普里姆(Prim)算法-克鲁斯卡尔(Kruskal)算法】_第1张图片

如图假设

表示9个村庄,现在需要在这9个村庄假设通信网络

村庄之间的数字代表村庄之间的直线距离,求用最小成本完成这9个村庄的通信网络建设

 

3.分析

这幅图只一个带权值的图,即网结构

 

如果无向连通图是一个网图

那么它的所有生成树中必有一颗边的权值总和最小的生成树,即最小生成树

连通网的最小生成树,经典的算法有两种:普里姆(Prim)算法 和 克鲁斯卡尔(Kruskal)算法

 

二:普里姆算法(Prim算法)

1.定义

A:图论中的一种算法

B:可在加权连通图里搜索最小生成树

意即由此算法搜索到的边子集所构成的树中

C:不但包括了连通图里的全部顶点(英语:Vertex (graph theory))

D:其全部边的权值之和亦为最小

 

历史由来:

该算法于1930年由捷克数学家沃伊捷赫·亚尔尼克(英语:Vojtěch Jarník)发现

并在1957年由美国计算机科学家罗伯特·普里姆(英语:Robert C. Prim)独立发现

1959年,艾兹格·迪科斯彻再次发现了该算法

 

因此,在某些场合,普里姆算法又被称为DJP算法、亚尔尼克算法或普里姆-亚尔尼克算法

2.算法步骤

数据结构—— 最小生成树连通网的两种算法区别和用法【普里姆(Prim)算法-克鲁斯卡尔(Kruskal)算法】_第2张图片

A:从图中某一个顶点出发(这里选寻找它相连的所有结点,比较这些结点的权值大小,然后连接权值最小的那个结点。(这里是

B:然后将寻找这两个结点相连的所有结点,找到权值最小的连接。(这里是

C:重复上一步,知道所有结点都连接上

数据结构—— 最小生成树连通网的两种算法区别和用法【普里姆(Prim)算法-克鲁斯卡尔(Kruskal)算法】_第3张图片

3.算法简单描写叙述

A:输入:

一个加权连通图。当中顶点集合为V,边集合为E;

 

B:初始化:

Vnew = {x},当中x为集合V中的任一节点(起始点),Enew = {},为空;

 

C:反复下列操作,直到Vnew = V:

       a.在集合E中选取权值最小的边,当中u为集合Vnew中的元素

          而v不在Vnew集合当中。而且v∈V

        (如果存在有多条满足前述条件即具有同样权值的边,则可随意选取当中之中的一个);

        b.将v增加集合Vnew中,将边增加集合Enew中。

 

D:输出:

使用集合Vnew和Enew来描写叙述所得到的最小生成树。

4.图例描写叙述

图例 说明 不可选 可选 已选(Vnew)
 

数据结构—— 最小生成树连通网的两种算法区别和用法【普里姆(Prim)算法-克鲁斯卡尔(Kruskal)算法】_第4张图片

此为原始的加权连通图。每条边一側的数字代表其权值。 - - -

数据结构—— 最小生成树连通网的两种算法区别和用法【普里姆(Prim)算法-克鲁斯卡尔(Kruskal)算法】_第5张图片

顶点D被随意选为起始点。顶点ABEF通过单条边与D相连。A是距离D近期的顶点。因此将A及对应边AD以高亮表示。 C, G A, B, E, F D
 

数据结构—— 最小生成树连通网的两种算法区别和用法【普里姆(Prim)算法-克鲁斯卡尔(Kruskal)算法】_第6张图片

下一个顶点为距离DA近期的顶点。BD为9,距A为7。E为15。F为6。因此,FDA近期,因此将顶点F与对应边DF以高亮表示。

 

 

C, G B, E, F A, D
数据结构—— 最小生成树连通网的两种算法区别和用法【普里姆(Prim)算法-克鲁斯卡尔(Kruskal)算法】_第7张图片 算法继续反复上面的步骤。距离A为7的顶点B被高亮表示。

 

 

C B, E, G A, D, F
 

数据结构—— 最小生成树连通网的两种算法区别和用法【普里姆(Prim)算法-克鲁斯卡尔(Kruskal)算法】_第8张图片

在当前情况下,能够在CEG间进行选择。CB为8,EB为7,GF为11。E近期。因此将顶点E与对应边BE高亮表示。

 

 

C, E, G A, D, F, B
 

数据结构—— 最小生成树连通网的两种算法区别和用法【普里姆(Prim)算法-克鲁斯卡尔(Kruskal)算法】_第9张图片

这里。可供选择的顶点仅仅有CGCE为5。GE为9,故选取C,并与边EC一同高亮表示。

 

 

C, G A, D, F, B, E

数据结构—— 最小生成树连通网的两种算法区别和用法【普里姆(Prim)算法-克鲁斯卡尔(Kruskal)算法】_第10张图片

顶点G是唯一剩下的顶点,它距F为11,距E为9,E近期。故高亮表示G及对应边EG G A, D, F, B, E, C

数据结构—— 最小生成树连通网的两种算法区别和用法【普里姆(Prim)算法-克鲁斯卡尔(Kruskal)算法】_第11张图片

如今,全部顶点均已被选取,图中绿色部分即为连通图的最小生成树。在此例中,最小生成树的权值之和为39。 A, D, F, B, E, C, G

5.普利姆(Prim)算法适用于求解无向图中的最小生成树

数据结构—— 最小生成树连通网的两种算法区别和用法【普里姆(Prim)算法-克鲁斯卡尔(Kruskal)算法】_第12张图片数据结构—— 最小生成树连通网的两种算法区别和用法【普里姆(Prim)算法-克鲁斯卡尔(Kruskal)算法】_第13张图片数据结构—— 最小生成树连通网的两种算法区别和用法【普里姆(Prim)算法-克鲁斯卡尔(Kruskal)算法】_第14张图片

数据结构—— 最小生成树连通网的两种算法区别和用法【普里姆(Prim)算法-克鲁斯卡尔(Kruskal)算法】_第15张图片数据结构—— 最小生成树连通网的两种算法区别和用法【普里姆(Prim)算法-克鲁斯卡尔(Kruskal)算法】_第16张图片数据结构—— 最小生成树连通网的两种算法区别和用法【普里姆(Prim)算法-克鲁斯卡尔(Kruskal)算法】_第17张图片

选择一个节点开始,比如V1进入集合U,剩下的集合的V-U包括剩下的节点,然后寻找从集合U到集合V-U最近的路径。这里有三条路径分别是权重为6到V2,权重为5到V4以及权重为1到V3,显然到通过V3连接而集合U和集合V-U是最近的,选择V3进入集合U。同样继续选择到V-U的路径,此时有6条可选路径,分别是权为6到V2【从V1】,权为5到V4【从V1】,权为5到V2【从V3】,权为5到V4【从V3】,权为6到V5【从V3】,权为4到V6【从V3】。选择出从V3到V6的路径并将V6添加至集合U中。按照这种方法依次将V4,V2和V5添加到集合U直到U和全体节点结合V相等,或者说V-U集合为空时结束,这时选出的n-1条边即为最小生成树

6.简单证明prim算法

反证法:如果prim生成的不是最小生成树

1).设prim生成的树为G0

2).如果存在Gmin使得cost(Gmin)不属于G0

3).将增加G0中可得一个环。且不是该环的最长边(这是由于∈Gmin)

4).这与prim每次生成最短边矛盾

5).故如果不成立,命题得证.

7.算法代码实现(未检验)

#define MAX  100000
#define VNUM  10+1                                             //这里没有ID为0的点,so id号范围1~10

int edge[VNUM][VNUM]={/*输入的邻接矩阵*/};
int lowcost[VNUM]={0};                                         //记录Vnew中每一个点到V中邻接点的最短边
int addvnew[VNUM];                                             //标记某点是否增加Vnew
int adjecent[VNUM]={0};                                        //记录V中与Vnew最邻近的点


void prim(int start)
{
     int sumweight=0;
     int i,j,k=0;

     for(i=1;i

8.时间复杂度

这里记顶点数v,边数e

邻接矩阵:O(v2)                

邻接表:O(elog2v)

 

三:克鲁斯卡尔(Kruskal)算法

1.定义

Kruskal算法是一种用来寻找最小生成树的算法,由Joseph Kruskal在1956年发表

用来解决同样问题的还有Prim算法和Boruvka算法等

三种算法都是贪婪算法的应用

和Boruvka算法不同的地方是

Kruskal算法在图中存在同样权值也有效

2.算法步骤

A:从某一顶点为起点

 

B:逐步找各个顶点最小权值的边来构成最小生成树

 

那我们也可以直接从边出发,寻找权值最小的边来构建最小生成树

不过在构建的过程中要考虑是否会形成环的情况

数据结构—— 最小生成树连通网的两种算法区别和用法【普里姆(Prim)算法-克鲁斯卡尔(Kruskal)算法】_第18张图片

3.算法简单描写叙述

A:记Graph中有v个顶点

e个边

 

B:新建图Graphnew

Graphnew中拥有原图中同样的e个顶点,但没有边

 

C:将原图Graph中全部e个边按权值从小到大排序

 

D:循环:

             从权值最小的边開始遍历每条边 直至图Graph中全部的节点都在同一个连通分量中

                if 这条边连接的两个节点于图Graphnew中不在同一个连通分量中

                                         增加这条边到图Graphnew中

4.图例描写叙述

首先第一步。我们有一张图Graph,有若干点和边 

数据结构—— 最小生成树连通网的两种算法区别和用法【普里姆(Prim)算法-克鲁斯卡尔(Kruskal)算法】_第19张图片

 

将全部的边的长度排序,用排序的结果作为我们选择边的根据。

这里再次体现了贪心算法的思想。资源排序,对局部最优的资源进行选择,排序完毕后。我们领先选择了边AD。这样我们的图就变成了右图

数据结构—— 最小生成树连通网的两种算法区别和用法【普里姆(Prim)算法-克鲁斯卡尔(Kruskal)算法】_第20张图片

在剩下的变中寻找。我们找到了CE。

这里边的权重也是5

数据结构—— 最小生成树连通网的两种算法区别和用法【普里姆(Prim)算法-克鲁斯卡尔(Kruskal)算法】_第21张图片

依次类推我们找到了6,7,7,即DF。AB,BE。

数据结构—— 最小生成树连通网的两种算法区别和用法【普里姆(Prim)算法-克鲁斯卡尔(Kruskal)算法】_第22张图片

以下继续选择, BC或者EF虽然如今长度为8的边是最小的未选择的边。可是如今他们已经连通了(对于BC能够通过CE,EB来连接,相似的EF能够通过EB,BA,AD,DF来接连)。所以不须要选择他们。

相似的BD也已经连通了(这里上图的连通线用红色表示了)。

最后就剩下EG和FG了。当然我们选择了EG。

最后成功的图

 

5.Kruskal算法构造最小生成树的过程图解 

数据结构—— 最小生成树连通网的两种算法区别和用法【普里姆(Prim)算法-克鲁斯卡尔(Kruskal)算法】_第23张图片数据结构—— 最小生成树连通网的两种算法区别和用法【普里姆(Prim)算法-克鲁斯卡尔(Kruskal)算法】_第24张图片数据结构—— 最小生成树连通网的两种算法区别和用法【普里姆(Prim)算法-克鲁斯卡尔(Kruskal)算法】_第25张图片

数据结构—— 最小生成树连通网的两种算法区别和用法【普里姆(Prim)算法-克鲁斯卡尔(Kruskal)算法】_第26张图片数据结构—— 最小生成树连通网的两种算法区别和用法【普里姆(Prim)算法-克鲁斯卡尔(Kruskal)算法】_第27张图片数据结构—— 最小生成树连通网的两种算法区别和用法【普里姆(Prim)算法-克鲁斯卡尔(Kruskal)算法】_第28张图片

Kruskal则是采取另一种思路,即从边入手

 

A:首先n个顶点分别视为n个连通分量

 

B:然后选择一条权重最小的边

如果边的两端分属于两个连通分量,就把这个边加入集合E

否则舍去这条边而选择下一条代价最小的边

 

C:依次类推,直到所有节点都在同一个连通分量上

6.简单证明Kruskal算法

对图的顶点数n做归纳,证明Kruskal算法对随意n阶图适用

 

A:归纳基础:

n=1。显然能够找到最小生成树

 

B:归纳过程:

如果Kruskal算法对n≤k阶图适用

那么,在k+1阶图G中

 

我们把最短边的两个端点a和b做一个合并操作,即把u与v合为一个点v'

把原来接在u和v的边都接到v'上去

这样就能够得到一个k阶图G'(u,v的合并是k+1少一条边),G'最小生成树T'能够用Kruskal算法得到

我们证明T'+{}是G的最小生成树。

用反证法,如果T'+{}不是最小生成树,最小生成树是T。即W(T)})。

显然T应该包括,否则,能够用增加到T中,形成一个环,删除环上原有的随意一条边,形成一棵更小权值的生成树。而T-{}。是G'的生成树。所以W(T-{})<=W(T')。也就是W(T)<=W(T')+W()=W(T'+{}),产生了矛盾。于是如果不成立。T'+{}是G的最小生成树。Kruskal算法对k+1阶图也适用。

由数学归纳法,Kruskal算法得证

 

7.算法代码实现(未检验)

typedef struct          
{        
    char vertex[VertexNum];                                //顶点表         
    int edges[VertexNum][VertexNum];                       //邻接矩阵,可看做边表         
    int n,e;                                               //图中当前的顶点数和边数         
}MGraph; 
 
typedef struct node  
{  
    int u;                                                 //边的起始顶点   
    int v;                                                 //边的终止顶点   
    int w;                                                 //边的权值   
}Edge; 

void kruskal(MGraph G)  
{  
    int i,j,u1,v1,sn1,sn2,k;  
    int vset[VertexNum];                                    //辅助数组。判定两个顶点是否连通   
    int E[EdgeNum];                                         //存放全部的边   
    k=0;                                                    //E数组的下标从0開始   
    for (i=0;i %d, %d",E[j].u,E[j].v,E[j].w);       
            k++;  
            for (i=0;i

8.时间复杂度

时间复杂度:elog2e 

e为图中的边数

 

四:对比

假设网中有n个节点和e条边

 

普利姆算法的时间复杂度是O(n^2)

克鲁斯卡尔算法的时间复杂度是O(eloge)

 

可以看出前者与网中的边数无关

后者相反

 

因此

普利姆算法适用于边稠密的网络

克鲁斯卡尔算法适用于求解边稀疏的网

 

参考地址:

1.【数据结构】最小生成树之普里姆(Prim)算法和克鲁斯卡尔(Kruskal)算法

https://www.jianshu.com/p/683ffde4f3a3

2.最小生成树-Prim算法和Kruskal算法

https://www.cnblogs.com/zhchoutai/p/8687614.html

3.Prim算法和Kruskal算法介绍

https://www.cnblogs.com/lbrs/p/11879357.html

 

你可能感兴趣的:(数据结构)