一、普里姆算法(Prim)
1、條件:圖爲鄰接矩陣結構(Adjacency List)
2、原理:假設 WN=(V,{E}) 是一個含有 n 個頂點的連通網,TV 是 WN 上最小生成樹中頂點的集合,TE 是最小生成樹中邊的集合。顯然,在算法執行結束時,TV=V,而 TE 是 E 的一個子集。在算法開始執行時,TE 爲空集,TV 中只有一個頂點,因此,按普里姆算法構造最小生成樹的過程爲:在所有“其一個頂點已經落在生成樹上,而另一個頂點尚未落在生成樹上”的邊中取一條權值爲最小的邊,逐條加在生成樹上,直至生成樹中含有 n-1條邊爲止
3、code
void MiniSpanTree_Prim(MGraph G) { int min,i,j,k; int adjvex[MAXVEX]; /*保存相關頂點下標*/ int lowcost[MAXVEX]; /*保存相關頂點的權值,存放的是最小生成樹到剩下頂點的最小權值*/ int lowcost[0]=0; /*初始化第一個權值爲0,即v0加入生成樹,假設v0下標爲0*/ for(i=1;i<G.numVertexes;i++) { lowcost[i]=G.arc[0][i]; /*arc爲鄰接矩陣的弧數組*/ /*將第一個頂點v0與之有邊的權值存入數組*/ adjvex[i]=0; /*初始化都爲v0的下標*/ } for(i=1;i<G.numVertexes;i++) { min=INFINITY; /*初始化最小權限值爲∞,便於比較*/ j=1;i=0; while(j<G.numVertexes) { if(lowcost[j]!=0&&lowcost[j]<min) /*lowcost[j]==0表示已將該頂點歸入生成樹了,不必比較了*/ { min=lowcost[j]; /*當前權值爲最小值*/ k=j; /*記錄該值*/ } j++; } printf("(%d,%d)",adjvex[k],k); /*即adjvex[k]頂點與k頂點之間有同路*/ lowcost[k]=0; /*將當前頂點的權值設爲0,表示將該頂點歸入生成樹*/ for(j=1;j<G.numVertexes;j++) { /*下面的循環的意思是在所有“其一個頂點已經落在生成樹上,而另一個頂點尚未落在生成樹上”的邊中取一條權值爲最小的邊*/ if(lowcost[j]!=0 && G.arc[k][j]<lowcost[j]) { /*若下標爲k頂點各個權值小於此前這些頂點未被加入生成樹權值*/ lowcost[j]=G.arc[k][j]; /*將較小的權值存入lowcost*/ adjvex[j]=k; /*將小標爲k的頂點存入adjvex*/ } } } }
一、克魯斯卡爾算法(Kruskal)
1、條件:邊集數組結構(Edge)
2、原理:設有一個有n個頂點的連通網N={V,E},最初先構造一個只有n個頂點,沒有邊的非連通圖T={V, E},圖中每個頂點自成一個連通分量。當在E中選到一條具有最小權值的邊時,若該邊的兩個頂點落在不同的連通分量上,則將此邊加入到T中;否則將此邊捨去,重新選擇一條權值最小的邊。如此重複下去,直到所有頂點在同一個連通分量上爲止。
3、code
/*對編輯數組Edge結構的定義*/ typedef struct { int begin; /*起始頂點下標*/ int end; /*終止頂點下標*/ int weight; /*權值*/ }Edge;
/*Kruskal算法生成最小生成樹*/ void MiniSpanTree_Kruskal(MGraph G) { int i,n,m; Edge edges[MAXEDGE]; /*定義邊集數組*/ int parent[MAXVEX]; /*定義一數組用來判斷邊與邊是否行程環路*/ /*此處省略將鄰接矩陣G轉化爲邊集數組edges並按權由小到大排序的代碼*/ for(i=0;i<G.numVertexes;i++) { parent[i]=0; /*初始化數組值爲0*/ } for(i=0;i<G.numVertexes;i++) { n=Find(parent,edges[i].begin); m=Find(parent,edges[i].end); if(n!=m) /*說明此邊沒有與現有的生成樹行程環路*/ { parent[n]=m; /*將此邊的結尾頂點放入小標爲起點的parent中*/ /*表示n與m在同一個集合中*/ printf("(%d,%d) %d",edges[i].begin,edges[i].end,edges[i].weight); } } } int Find(int *parent,int f) /*查找連線頂點的尾部下標*/ { while(parent[f]>0) f=parent[f]; return f; }