《算法设计与分析》-最小生成树随笔

博客介绍了无向连通带权图的最小生成树概念,即包含所有顶点且边权总和最小的生成树。还阐述了最小生成树性质,介绍了Prim和Kruskal两种贪心算法来构造最小生成树,给出Prim算法基本思想与代码段,对比了两种算法在不同边数情况下的优劣。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、概述:设G=(V,E)是无向连通带权图,即一个网络。E中每条边(v,w)的权为c[v][w]。如果G的子图G~是一颗包含G的所有顶点的树,则称G~为G的生成树。并且生成树上面的各边权的总和称为该生成树的耗费。所以在所有的G的生成树中,消耗最小的生成树就是G的最小生成树。

2、最小生成树性质:其中Prim和Kruskal算法都是可以看做设计贪心算法策略的例子。

设G=(V,E)是一个连通网络,U是顶点集V的一个非空真子集。若(u,v)是G中一条“一个端点在U中(例如:u∈U),另一个端点不在U中的边(例如:v∈V-U),且(u,v)具有最小权值,则一定存在G的一棵最小生成树包括此边(u,v)。

3、Prim算法:设置G=(V,E)是连通的带权图,V={1,2,。。。,n}。构造G的最小生成树的Prim算法的基本思想是:首先置S={1},然后,只要S是V的真子集,就进行该贪心选择吧:选取满足条件的i属于S,j属于V-S,且c[i][j]最小的边,将顶点j添加到S中。所以最后进行到S=V为止即可。

下面贴出Prim算法的代码段:

public static void prim(int n,float[][] c){
//prim算法
float[] lowcost = new float[n+1];
int[] closest = new int[n+1];
boolean[] s = new boolean[n+1];
s[1] = true;
for(int i =2;i<=n;i++){
lowcost[i] = c[1][i];
closest[i] = 1;
s[i] = false;
}

for(int i =1;i<n;i++){
float = min = Float.MAX_VALUE;
int j = 1;
for(int k =2;k<=n;k++){
if((lowcost[k]<min)&&(!s[k])){
min = lowcost[k];
j = k;
s[j] = true;
for(int k = 2;k<=n;k++)
if((c[j][k] < lowcost[k])&&(!s[k])){
lowcost[k] = c[j][k];
closest[k] = j;
}
}
}
所以上述的prim所需要的计算时间为O(n2)。

4、KrusKal算法:当图的边数为e时,KrusKal算法的所需要的时间是O(eloge)。当e=O(n2)时,该算法要比Prim算法差一些,但是当e=o(n2)时,该算法要好得多。

  我们给定无向连通带权图G=(V,E),V={1,2,。。。,n}。KrusKal算法构造的思想为:首先将n个顶点看作是n个孤立的分支。将所有边按照权值大小从小到大的排序,从第一条边开始依次顺序的查看每一条边,当查看到第k条边(v,w)时,如果端点v和w分别是当前两个不同的连通分支T1和T2中的顶点时,就使用边(v,w)将T1和T2连接成为一个连通分支,然后继续查看第k+1条边;如果端点v和w在当前的同一个连通分支中,就直接在查看第k+1条边。这个过程进行到只剩下一条边为止即可,此时这个连通分支就是G的一颗最小生成树。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值