【最小生成樹】prim演算法
阿新 • • 發佈:2018-11-29
演算法分析的一般步驟:
1、文字描述:如果一個演算法文字描述不清楚,就說明思路不清楚,也不可能寫好。
prim演算法是實現圖的最小生成樹。既然是圖,就假設包含n個頂點,m條邊。prim演算法是從頂點出發的,其演算法時間複雜度與頂點數目有關係。
(注意:prim演算法適合稠密圖,其時間複雜度為O(n^2),其時間複雜度與邊得數目無關,而kruskal演算法的時間複雜度為O(eloge)跟邊的數目有關,適合稀疏圖。)
演算法思路:從某個頂點開始,假設v0,此時v0屬於最小生成樹結點中的一個元素,該集合假設u,剩下的V-v0為待判定的點,此時選取u中的頂點到V-v0中頂點的一個路徑最小的邊,並且將其中非u中的頂點加入到u中,迴圈直到u中的頂點包含圖所有的頂點為止。
演算法在選取最小路徑的時候需要優化,具體思路:w[]陣列儲存各個頂點的最短路徑,b[]陣列儲存到i頂點最短路徑的頂點,比如,到0號頂點最短的路徑是<v0,v3>,那麼w[0]=<v0,v3>,b[0]=3;這樣每次找最小路徑就不是o(n*n)的代價了。
2、舉例說明:
3、程式實現與說明:
#include <stdio.h> #include <stdlib.h> #define count 6 void prim(int a[][count],int u[],int w[],int b[],int n) { int i=0,j=0,m=0,min=100; for(i=0;i<count;i++) { u[i]=0;//初始化0,說明沒有訪問過 w[i]=a[0][i];//初始每個頂點最短路徑為到0頂點的距離 b[i]=0;//初始每個頂點都指向0頂點 } u[0]=1;//賦值1,從0頂點開始 for(i=1;i<n;i++) { min=100; j=0; for(m=1;m<n;m++) { if(!u[m] && w[m]<min)//很關鍵,得到到訪問頂點到未訪問頂點的最短路徑以及對應頂點j { min=w[m]; j=m; } } u[j]=1;//把下一個頂點標為已訪問 printf("%d,%d\n",j+1,b[j]+1);//輸出結果 for(m=1;m<n;m++) { if(!u[m] && a[j][m]<w[m])//此時,u集合裡面多了一個頂點j,要重新更新最短路徑以及對應的頂點 { w[m]=a[j][m]; b[m]=j; } } } } int main() { int u[count],w[count],b[count],a[count][count]; int i=0,j=0; for(i=0;i<count;i++) { for(j=0;j<count;j++) { a[i][j]= 100; } } a[0][1]=6,a[0][2]=1,a[0][3]=5; a[1][0]=6,a[1][2]=5,a[1][4]=3; a[2][0]=1,a[2][1]=5,a[2][3]=5,a[2][4]=6,a[2][5]=4; a[3][0]=5,a[3][2]=5,a[3][5]=2; a[4][1]=3,a[4][2]=6,a[4][5]=6; a[5][3]=2,a[5][2]=4,a[5][4]=6; prim(a,u,w,b,count); return 0; }
4、時間複雜度:o(n*n)
參考部落格:https://www.cnblogs.com/nannanITeye/p/3446424.html