克魯斯卡爾最短路徑演算法詳解
阿新 • • 發佈:2019-01-01
void InsertSort(Edge a[],int n) //這裡是插入排序,就是對傳入的陣列進行從小到大的排序,方便克魯斯卡爾演算法的執行 { int i,j,k; Edge temp; for(i=1;i<n;i++) { temp = a[i]; //建立一個輔助變數, j=i-1; //將每一次陣列的第一個值與第二個比較 while(j>=0&&temp.w<a[j].w) //大則互換,也叫插入換位 { a[j+1]=a[j]; j--; } a[j+1]=temp; } // /*for(i=0;i<n;i++) /printf("%d ",a[i].w);printf("\n");*/ //這兩//句是我用來輔助你去看它的生成結果,在實際程式中可要可不要 } void Kruskal(MGraph g) //克魯斯卡爾演算法最小生成樹 { int i,j,m1,m2,sn1,sn2,k; int vset[MAXV]; //輔助陣列 ,用於放最小生成樹節點 Edge E[MAXE]; //邊集 k=0; //邊數變數 //下面兩個for實際上是將圖的矩陣中的資料放入陣列中,你去看課本上的圖的矩陣,就明白了,INF是無窮大的意思, 矩陣是方矩陣,長寬各為g.n for(i=0;i<g.n;i++) for(j=0;j<g.n;j++) if(g.edges[i][j]!=0&&g.edges[i][j]!=INF) { E[k].u=i;E[k].v=j;E[k].w=g.edges[i][j]; k++; } InsertSort(E,k); //邊插入排序,就是將權值從小到大依次排列 for(i=0;i<g.n;i++) //初始化輔助陣列,儲存最小生成樹節點的編號 vset[i]=i; //初始化為 0.1.2.3.4.5,作用後面就知道了 //vset[]這個陣列是用來輔助克魯斯卡爾演算法的陣列,在後面中用來判斷是否會形成迴路,因為一旦形成迴路就不滿足生成樹的概念,然後你再去看最小生成樹,就是 權值之和最小並且遍歷了節點,並且只遍歷了一次 ,此時就生成了最小生成樹 k=1; //k表示當前構造最小生成樹的第幾條邊,初值為1 j=0; //E中邊的下標,初值0 while(k<g.n) //生成邊數小於n時迴圈 { m1=E[j].u;m2=E[j].v; //取一條邊的頭尾頂點E[j].u和E[j].v是同步變化的 sn1=vset[m1]; sn2=vset[m2]; //分別得到兩個頂點所屬的集合編號 //sn1和sn2頁是在同時變化,注意值,最好是將while這個過程畫出來 if(sn1!=sn2) //兩頂點屬於不同的集合, { //該邊是最小生成樹的一條邊 printf(" (%d,%d):%d\n",m1,m2,E[j].w); k++; //生成邊數加1 for(i = 0;i<g.n;i++) //兩個集合統一編號,統一為小值這裡就是判斷是否形成迴路了,迴圈檢查,如果有相等,直接跳過 if(vset[i]==sn2) //集合編號為sn2的改為sn1 vset[i]=sn1; } j++; //掃描下一條邊 } }