最小產生樹的另一種演算法,比較適合處理稀疏圖。演算法思想:按權值的遞增次序選擇合適的邊來構造最小產生樹。
以下程式碼封裝含無向帶權圖的建立,Kruskal演算法的完整過程。請觀看【動畫示範Kruskal演算法
】,驗證程式是否正確。
代碼說明:
1.vest[]數組存放兩個頂點間的連通分量
2.結構體E[]數組是按權值從小到大排列的邊集
3.對E的排序採用了qsort排序,自訂的排序函數是對結構體的二級排序
給定的帶權無向圖如下:
實現的完整代碼如下:
#include <iostream><br />#include <stdlib.h>//使用快排函數<br />using namespace std;<br />#define MaxVertexNum 100 //最大的頂點數<br />#define MaxEdgeNum 100//最大的邊數<br />#define INF 32767 //將無法到達的權值無限大設為32767<br />typedef char VertexType;<br />typedef int EdgeType;<br />typedef struct<br />{<br /> VertexType vertex[MaxVertexNum]; //頂點表<br /> EdgeType edges[MaxVertexNum][MaxVertexNum]; //鄰接矩陣,可看做邊表<br /> int n,e; //圖中當前的頂點數和邊數<br />}MGraph;<br />void CreateMGraph(MGraph &G)<br />{<br /> int i,j,k,m;<br /> cout<<"請輸入頂點數和邊數:";<br /> cin>>G.n>>G.e;<br /> cout<<"請輸入頂點元素:";<br /> for (i=0;i<G.n;i++)<br /> {<br /> cin>>G.vertex[i];<br /> }<br /> for (i=0;i<G.n;i++)<br /> {<br /> for (j=0;j<G.n;j++)<br /> {<br /> G.edges[i][j]=INF; //初始化無限大權值<br /> if (i==j)<br /> {<br /> G.edges[i][j]=0; //對角線為0<br /> }<br /> }<br /> }<br /> // 無向網圖的建立<br /> cout<<"請輸入邊兩端頂點序號和相應的權值:/n";<br /> for (k=0;k<G.e;k++)<br /> {<br /> cin>>i>>j>>m;<br /> G.edges[i][j]=m;<br /> //G.edges[j][i]=m; //對稱矩陣,這裡只存入上三角。<br /> }<br />}<br />typedef struct node<br />{<br />int u;//邊的起始頂點<br />int v;//邊的終止頂點<br />int w;//邊的權值<br />}Edge;<br />int cmp( const void *a , const void *b )<br />{<br /> struct node *c = (node *)a;<br /> struct node *d = (node *)b;<br /> if(c->w != d->w) return c->w - d->w;<br /> else return d->u - c->u;<br />}<br />void kruskal(MGraph G)<br />{<br />int i,j,u1,v1,sn1,sn2,k;<br />int vset[MaxVertexNum];//輔助數組,判定兩個頂點是否連通<br />Edge E[MaxEdgeNum];//存放所有的邊<br />k=0;//E數組的下標從0開始<br />for (i=0;i<G.n;i++)<br />{<br />for (j=0;j<G.n;j++)<br />{<br />if (G.edges[i][j]!=0 && G.edges[i][j]!=INF)<br />{<br />E[k].u=i;<br />E[k].v=j;<br />E[k].w=G.edges[i][j];<br />k++;<br />}<br />}<br />}<br />qsort(E,k,sizeof(E[0]),cmp);//快速排序,按權值從小到大排列<br />for (i=0;i<G.n;i++)//初始化輔助數組<br />{<br />vset[i]=i;<br />}<br />k=1;//產生的邊數,最後要剛好為總邊數<br />j=0;//E中的下標<br />while (k<G.n)<br />{<br />u1=E[j].u;<br />v1=E[j].v;<br />sn1=vset[u1];<br />sn2=vset[v1];//得到兩頂點屬於的集合編號<br />if (sn1!=sn2)//不在同一集合編號內的話,把邊加入最小產生樹<br />{<br />cout<<"( "<<G.vertex[u1]<<"--->"<<G.vertex[v1]<<" ) "<<E[j].w<<endl;<br />k++;<br />for (i=0;i<G.n;i++)<br />{<br />if (vset[i]==sn2)<br />{<br />vset[i]=sn1;<br />}<br />}<br />}<br />j++;<br />}<br />}<br />int main()<br />{<br />MGraph G;<br />CreateMGraph(G);<br />kruskal(G);<br />return 0;<br />}
程式測試結果如下: