老物了,網上的例子多的數不過來。不過我還是有必要練習一下的。
之所以看這個算法是因為最近在看顏色聚合向量時,有的論文用到了最小生成樹,因此我就拿來熟悉一下。
Kruskal算法類似於連通分支算法,感覺和過去實現過的連通區域標記算法非常像。
步驟:
1.對於一個圖,將圖的每條邊提取出來從小到大進行排序。
2.將已排序的邊依次加入到新圖中,如果新圖中出現了環,那么就舍棄這條邊。
3.不斷重復第二步。
下面兩個圖就是kruskal算法前后的樣子。
代碼如下:
main.m
clear all; close all; clc; %算法導論P349的列子 G=[0 4 0 0 0 0 0 8 0; 4 0 8 0 0 0 0 11 0; 0 8 0 7 0 4 0 0 2; 0 0 7 0 9 14 0 0 0; 0 0 0 9 0 10 0 0 0; 0 0 4 14 10 0 2 0 0; 0 0 0 0 0 2 0 1 6; 8 11 0 0 0 0 1 0 7; 0 0 2 0 0 0 6 7 0]; [m n]=size(G); E=[]; k=0; %邊的數量 for i=1:m for j=i:n if G(i,j)~=0 E=[E;G(i,j) i j]; %提取邊,三元組存儲 k=k+1; end end end for i=k:-1:1 %按邊的權重排序,小的排前面 for j=1:i-1 if E(j,1)>E(j+1,1) tmp=E(j,:); E(j,:)=E(j+1,:); E(j+1,:)=tmp; end end end A=zeros(m,n); for i=1:k A(E(i,2),E(i,3))=E(i,1); A(E(i,3),E(i,2))=E(i,1); if huan(A) %加入邊后判斷圖中是否含有環 A(E(i,2),E(i,3))=0; A(E(i,3),E(i,2))=0; end end
huan.m
function re=huan(A) [m n]=size(A); while 1 pre_A=A; for i=1:m du=0; %第m個元素的度 for j=1:n if A(i,j)~=0 du=du+1; end end if du==1 %元素的度為1時刪除這個元素,其相鄰元素度減一 A(i,:)=0; A(:,i)=0; end end if pre_A==A %圖中沒有度為1的元素則退出 break; end end if sum(A(:))==0 re=0; else re=1; end end