最小生成树问题prim/Kruskal算法

问题:
在这里插入图片描述求该图最小生成树
1.prim算法
标准描述
设置两个集合 P 和 Q ,其中 P 用于存放 G 的最小生成树中的顶点,集合 Q 存放 G的最小生成树中的边。令集合 P 的初值为 P = { v 1 } (假设构造最小生成树时,从顶点 v 1
出发),集合 Q 的初值为 Q = Φ 。prim 算法的思想是,从所有 p ∈ P , v ∈ V − P 的边
中,选取具有最小权值的边 pv ,将顶点 v 加入集合 P 中,将边 pv 加入集合 Q 中,如
此不断重复,直到 P = V 时,最小生成树构造完毕,这时集合 Q 中包含了最小生成树
的所有边。
prim 算法如下:
(i) P = { v 1 } , Q = Φ ;
(ii)while P ~ = V
找最小边 pv ,其中 p ∈ P , v ∈ V − P
P = P + { v }
Q = Q + { pv }
end

我对该算法的简单理解:
a.以顶点v1作为起始点,开始查找周边距离最近的顶点。
b.找到最近的顶点(本题为v2),除了v1,v2的中间连接边,以v1,v2作为出发点向四周寻找距离最近的点
c.重复直至遍历所有顶点

算法实现简单理解:
原始矩阵如下:
原始矩阵
以a(1,1)(即顶点v1)为出发点,摒弃第一列(因为行列代表的意思是一样的,所以我们把第一列删除),在第一行中查找最小值。
在这里插入图片描述
找到最小值为50,50属于顶点2(v2),于是以v1,v2作为一个出发点,摒弃第二列,在第一行和第二行中查找最小值。
在这里插入图片描述
如此,重复直到遍历全部顶点,找到最小生成树。
代码如下(来自姜守奎——数学建模算法与应用):

clc;clear;
a=zeros(7);
a(1,2)=50;a(1,3)=60;
a(2,4)=65;a(2,5)=40;
a(3,4)=52;a(3,7)=45;
a(4,5)=50;a(4,6)=30;a(4,7)=42;
a(5,6)=70;
a=a+a';a(a==0)=inf;
result=[];p=1;tb=2:length(a);
while size(result,2)~=length(a)-1
    temp=a(p,tb);
    temp=temp(:);  %行矩阵->列矩阵
    d=min(temp);
    [jb,kb]=find(a(p,tb)==d,1);
    j=p(jb);k=tb(kb);
    result=[result,[j;k;d]];p=[p,k];tb(find(tb==k))=[];
end
result

2.Kruskal算法
标准表述:
科茹斯克尔(Kruskal)算法是一个好算法。Kruskal 算法如下:
(i)选 e 1 ∈ E ( G ) ,使得 w ( e 1 ) = min 。
(ii)若 e 1 , e 2 , L , e i 已选好,则从 E ( G ) − { e 1 , e 2 , L , e i } 中选取 e i + 1 ,使得
1 G [{ e 1 , e 2 , L , e i , e i + 1 }] 中无圈,且
2 w ( e i + 1 ) = min 。
(iii)直到选得 e ν − 1 为止。
实现方式:
我们用 index 2 × n 存放各边端点的信息,当选中某一边之后,就将此边对应的顶点序
号中较大序号 u 改记为此边的另一序号 v ,同时把后面边中所有序号为 u 的改记为 v 。
此方法的几何意义是:将序号 u 的这个顶点收缩到 v 顶点, u 顶点不复存在。后面继续
寻查时,发现某边的两个顶点序号相同时,认为已被收缩掉,失去了被选取的资格。

实现代码:

clc;clear;
a=zeros(7);
a(1,2)=50;a(1,3)=60;
a(2,4)=65;a(2,5)=40;
a(3,4)=52;a(3,7)=45;
a(4,5)=50;a(4,6)=30;a(4,7)=42;
a(5,6)=70;
[i,j,b]=find(a);
data=[i';j';b'];index=data(1:2,:);
loop=length(a)-1;
result=[];
while length(result)<loop
    temp=min(data(3,:));
    flag=find(data(3,:)==temp);
    flag=flag(1);
    v1=index(1,flag);v2=index(2,flag);
    if v1~=v2
        result=[result,data(:,flag)];
    end
    index(find(index==v2))=v1;
    data(:,flag)=[];
    index(:,flag)=[];
end
result
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值