老物了,网上的例子多的数不过来。不过我还是有必要练习一下的。
之所以看这个算法是因为最近在看颜色聚合向量时,有的论文用到了最小生成树,因此我就拿来熟悉一下。
Kruskal算法类似于连通分支算法,感觉和过去实现过的连通区域标记算法非常像。
步骤:
1.对于一个图,将图的每条边提取出来从小到大进行排序。
2.将已排序的边依次加入到新图中,如果新图中出现了环,那么就舍弃这条边。
3.不断重复第二步。
下面两个图就是kruskal算法前后的样子。
代码如下:
main.m
1 clear all;
2 close all;
3 clc;
4 %算法导论P349的列子
5 G=[0 4 0 0 0 0 0 8 0;
6 4 0 8 0 0 0 0 11 0;
7 0 8 0 7 0 4 0 0 2;
8 0 0 7 0 9 14 0 0 0;
9 0 0 0 9 0 10 0 0 0;
10 0 0 4 14 10 0 2 0 0;
11 0 0 0 0 0 2 0 1 6;
12 8 11 0 0 0 0 1 0 7;
13 0 0 2 0 0 0 6 7 0];
14
15 [m n]=size(G);
16 E=[];
17 k=0; %边的数量
18 for i=1:m
19 for j=i:n
20 if G(i,j)~=0
21 E=[E;G(i,j) i j]; %提取边,三元组存储
22 k=k+1;
23 end
24 end
25 end
26
27 for i=k:-1:1 %按边的权重排序,小的排前面
28 for j=1:i-1
29 if E(j,1)>E(j+1,1)
30 tmp=E(j,:);
31 E(j,:)=E(j+1,:);
32 E(j+1,:)=tmp;
33 end
34 end
35 end
36
37 A=zeros(m,n);
38 for i=1:k
39 A(E(i,2),E(i,3))=E(i,1);
40 A(E(i,3),E(i,2))=E(i,1);
41 if huan(A) %加入边后判断图中是否含有环
42 A(E(i,2),E(i,3))=0;
43 A(E(i,3),E(i,2))=0;
44 end
45 end
huan.m
1 function re=huan(A)
2 [m n]=size(A);
3 while 1
4 pre_A=A;
5 for i=1:m
6 du=0; %第m个元素的度
7 for j=1:n
8 if A(i,j)~=0
9 du=du+1;
10 end
11 end
12 if du==1 %元素的度为1时删除这个元素,其相邻元素度减一
13 A(i,:)=0;
14 A(:,i)=0;
15 end
16 end
17 if pre_A==A %图中没有度为1的元素则退出
18 break;
19 end
20 end
21
22 if sum(A(:))==0
23 re=0;
24 else
25 re=1;
26 end
27 end