1. 程式人生 > >【最小生成樹】prim演算法

【最小生成樹】prim演算法

演算法分析的一般步驟:

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