Prim算法生成最小生成樹

一.先看代碼:

# include <stdio.h>
# include <stdlib.h>

# define max 20
# define INEF 9999999


//鄰接矩陣 
typedef struct node
{
    int  vexnum;//頂點的個數 
    int arcnum;//邊的個數 
    int arcs[max][max];
    char vex[max];//存放定點的信息 
}NODE, *PNODE;


//標誌數組 
typedef struct dd
{
    int adjvex;//存放與頂點權值小的頂點下標 
    int lowcost;//存放權值 
}LL;
LL closedge[max];


PNODE creat()//創建一個鄰接矩陣 
{
    int i, j;
   PNODE G;
   char enter;
   printf("請輸入定點的個數和邊數:\n");
   scanf("%d%d",&G->vexnum,&G->arcnum);
   for(i = 1; i<=G->vexnum; i++)//初始化二維數組 
   {
       for( j = 1; j<=G->vexnum; j++)
       {
          G->arcs[i][j] = INEF;     
      }
   }
   printf("請你輸入定點信息:\n");
   for(i = 1; i<=G->vexnum; i++)//初始化頂點的座標 
   {
      scanf("%c%c",&enter, &G->vex[i]);
   }
    printf("請輸入邊的信息(a,b,w)w爲邊的權值\n");
    for(i = 1; i<=G->arcnum; i++)//存放相應有權值的相應的座標 
    {
        int a,b,w;
        scanf("%d%d%d",&a,&b,&w);
        G->arcs[a][b] = w;
    }
    return G;
}



void Prim(PNODE G, int start)
{   
    char s1,s2;
    int i, e, k, m, min;
    closedge[start].lowcost = 0;
    s1 = G->vex[start];
    printf("%c ", s1);
    for(i = 1; i<=G->vexnum; i++)//給標誌數組初始化爲從出發點到每一個點(除自己外的)的權值 
    {
        if(i !=start)
        {
            closedge[i].adjvex = start;//標誌出發頂點的下標 
            closedge[i].lowcost = G->arcs[start][i]; 
        }
    }
    for(e = 1; e<G->vexnum; e++)
    {
        min = INEF;
        for(k = 1; k<=G->vexnum; k++)//在標誌數組中找到從出發點到其他點權值最小的下標, 這就是下次要走的路 
        {
            if(closedge[k].lowcost != 0 && closedge[k].lowcost < min)
            {
                min = closedge[k].lowcost;
                m  = k;
            }
        }

        printf("%c ",G->vex[m]);//輸出最近的一個點的座標 
        closedge[m].lowcost = 0;//將該點的標誌記爲訪問過 

        for(i = 1; i<=G->vexnum; i++)//用新的頂點來重新初始化各頂點邊的權值 
        {
            if((i!=m) && G->arcs[m][i]<closedge[i].lowcost) 
            {
               closedge[i].lowcost = G->arcs[m][i];
               closedge[i].adjvex = m; 
            }
        }
    }
}

int main(void)
{
    PNODE G = creat();
    Prim(G, 1);
    return 0;
} 

二.基本思想:

從連通網中的一個頂點出發,選擇與它關聯權值最小的邊,將其的頂點加入到生成樹的頂點集合u中,以後每一步從一個頂點在U中,而另一個頂點不在U中的各條邊中選擇最小的邊,並將它的頂點加入到集合U中,如此下去,直到所有的頂點全都加入到生成樹的頂點集合U中。

三.具體實現:

1:先建立一個鄰接矩陣將圖中的所有的頂點以及權值的信息都存放起來,然後,在創建一個結構體數組作爲標誌,
數組元素的下標對應與鄰接矩陣中頂點的下標。然後選擇一個頂點出發,輸出它的信息並將它標誌爲已訪問,
然後從鄰接矩陣中找出從這個點到其他除自己之外所有頂點的路徑長度。賦值給標誌數組中的lowcost。
2:然後在這個標誌數組中根據lowcost找出從離這個出發點距離最小的邊的值,以及頂點的下標。
3:現在到了關鍵的時刻,輸出你剛纔找到那個頂點的下標,並且根據下標將標誌數組中的lowcost賦值爲0表示該頂點已經訪問過,
然後在鄰接矩陣中找出該頂點到其他所有頂點的權值,與已經走過頂點到其他沒有走過頂點的權值(這個值記錄在標誌數組中)進行比較,

小知識

1:爲什麼要用鄰接矩陣存?
因爲整個算法通過比較標誌數組元素確定代價最小的邊,prim的時間複雜度爲O(n2),它取決於頂點的個數所以,它更適合於,頂點少邊多的情況(稠密圖).

例如:

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