最小生成树

n个点之间最多存在n(n-1)/2个边,但是在这么多点当中只需要n-1个边即可将n个点连接起来,称为生成树,这些的生成树中n-1个边的权值和最小的称为最小生成树。

如何生成最小生成树,基于最小生成树的MST性质,设顶点集为V,则存在其子集U和V-U,其一定含有一条权值最小的边(u,v)可以构成一个最小生成树。

普利姆算法:

设置一个辅助数组用以存放最小生成树的顶点。从一个顶点开始,先加入辅助数组,然后找到其权值最小的边,加入这个点至辅助数组中,再从辅助数组中的点开始找到其相邻的权值最小的边,依次这样下去,直至所有的点都在辅助数组中。

最小生成树_第1张图片

如上的无向图,从顶点1开始生成一个无向图:

将1加入辅助数组,寻找其相邻边:1->2:12   1->5:5    1->4:8

权值最小为5,将5加入辅助数组,现在多了一些邻接边:5->2:15   5->4:6   5->3:10   5->6:8

将4加入辅助数组,再寻找邻接边:4->6:4,将6加入。

在寻找邻接边:6->3:9,将3加入。邻接边:3->2:20,由于到达2的最小权值为:1->2:12,所以加入2这个点,但是路径为1->2。

最后生成的最小生成树为:

1->2

1->5->4->6->3.

上述的算法可以描述为:选取一个顶点,找寻其邻接边,判断邻接边的权值大小,将最小邻接边的顶点加入到辅助数组中,将辅助数组中的所有点的邻接边都找到,判断权值大小,将不在辅助数组中的最小的边对应的顶点加入,重复这个过程,直至所有的顶点均在辅助数组中。

void minTree(Graph G, Type u)

{

point=u;

site=Findnext(point);//找寻u的邻接边

point=min(site);//所有邻接边中权值最小边对应的点;

visited[point]=1;

for(point=0;point

if(visited[point]=1)

{

site=Findnext(point);

point=min(site);//所有邻接边中权值最小边对应的点;

visited[point]=1;

count++;

}

if(count>=G.max)

break;

}

上述方法可以很容易的得到结果。

克鲁斯卡尔算法:

将所有的带权边按照权值从小到大排好,然后依次挑选边,只要所选的边不成环即可,终止条件为选了n-1条边。

因此这个算法里有两个部分

1.按权值大小排序。

2.判断是否成环。

成环判断可以通过并查集的方法。

 

 

你可能感兴趣的:(最小生成树)