算法導論-最小生成樹-prim算法

關於最小生成樹的prim算法原理這裏不多做介紹了。與kruskal算法相比,都是利用了貪心策略來求最小生成樹,不同的是:

Kruskal算法中,集合A是一個森林;選擇最小的權值邊加入到森林。

Prim算法中,集合A則是一棵樹;每次加入到A中的安全邊永遠是連接A和A之外某個結點的邊中權重最小的邊。相當於樹的生長。

下面是Prim算法的代碼,裏面有詳細的註釋:

#include<stdio.h>
#include<stdlib.h>
#define n 9//圖中點的個數
#define max n*n//圖中的邊的個數
#define inf 9999//標示無窮大
struct edge{
    int u;//起點
    int v;//終點
    int value;//邊的權值
}e[max];
int p[n];//p[i]用於記錄依次加入最小生成樹的頂點

/*-----------------------------prim算法-----------------------------*/
int prim(int en[][n],int v)
{
    int i,j,k,kk=0,min=inf,count=0;//min標示無窮大,count用於記錄最小生成樹各邊的權值
    int lowcost[n];//lowcost[i]用於記錄頂點i到最小生成樹t中的頂點的最短路徑權值
    int intree[n];//intree[i]用於記錄頂點i是否在最小生成樹中,1:在;0:不在。
    for(i=0;i<n;i++)//初始化
    {
        if(en[i][v]==inf)//路徑不可達
            lowcost[i]=inf;
        else //有可達路徑
            lowcost[i]=en[i][v];
        intree[i]=0;
        p[i]=-1;
    }
    intree[v]=1;//標記頂點v爲最小生成樹中的頂點
    p[0]=v;
    for(i=0;i<n-1;i++)//選擇其餘的n-1個頂點
    {
        min=inf;
        for(j=0;j<n;j++)//選出到最小生成樹t中頂點最短的頂點k
        {
            if(intree[j]==0 && lowcost[j]<min)
            {
                min=lowcost[j];
                k=j;
            }
        }
        count=count+min;//記錄權值
        intree[k]=1;
        v=k;
        p[++kk]=k;//記錄依次加入最小生成樹的頂點
        /**
        **開始時,lowcost[]是記錄其他點到v(這時v是根結點)的距離
        **當新加入一個結點k後,令v=k,在剩下的未加入結點中尋找,如果v到某點j的距離小於lowcost[j],更新lowcost[j]
        **這也就是prim算法的貪心策略
        */
        for(j=0;j<n;j++)
        {
            if(intree[j]==0 && en[v][j]!=0 && en[v][j]<lowcost[j])
                lowcost[j]=en[v][j];
        }
    }
    return(count);
}
/*-----------------------------主函數-------------------------------*/
int main()
{
    int i,sum=0;
    char vex;
    //en表示各個點之間的連接情況,爲inf表示無邊,其他值表示邊的權值看 :)
    int en[n][n]={{0,4,inf,inf,inf,inf,inf,8,inf},
            {4,0,8,inf,inf,inf,inf,11,inf},
            {inf,8,0,7,inf,4,inf,inf,2},
            {inf,inf,7,0,9,14,inf,inf,inf},
            {inf,inf,inf,9,0,10,inf,inf,inf},
            {inf,inf,4,14,10,0,2,inf,inf},
            {inf,inf,inf,inf,inf,2,0,1,6},
            {8,11,inf,inf,inf,inf,1,0,7},
            {inf,inf,2,inf,inf,inf,6,7,0}};
    printf("輸入最小生成樹的構造開始頂點(a,b,c,d,e,f,g,h,i):\n");
    scanf("%c",&vex);
    sum=prim(en,vex-'a');
    printf("最小生成樹的代價爲:%d\n",sum);
    printf("構造最小生成樹依次加入樹的頂點爲:\n");
    for(i=0;i<n-1;i++)
        if(p[i]!=-1)
            printf("%c -> ",p[i]+'a');
        printf("%c\n",p[i]+'a');

    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章