1. 程式人生 > >【演算法筆記】普里姆Prim演算法的簡單實現

【演算法筆記】普里姆Prim演算法的簡單實現

前言

由於最近在學習資料結構,在學習的過程中動手把演算法的思路用程式碼的形式實現了,這樣記憶更深刻。所以在此記錄下學習普里姆演算法時,如何通過該演算法獲得連通網的最小生成樹。

演算法實現思路

一、建立以鄰接矩陣為儲存方式的帶權連通無向圖(連通網)
二、利用Prim演算法計算最小邊的權值之和
(1)從圖中任取一個頂點,把它當成一棵樹,並用vest[]記錄頂點是否在生成樹中
(2)從圖中選取與該樹相接的邊中權值最小的邊,並將與該邊連線的頂點併入樹中
(3)重複步驟2直到圖中所有頂點都被併入樹中為止

演算法實現程式碼

#include <stdio.h>
#include <stdlib.h>
//圖的鄰接矩陣儲存結構 typedef char VertexType; typedef int EdgeType; #define MAXVEX 100 //最大頂點數 #define INFINITY 65535 //用65535代表無窮遠,表示不相鄰 typedef struct { VertexType vexs[MAXVEX];//頂點表 EdgeType arc[MAXVEX][MAXVEX];//鄰接矩陣,可看作邊表 int vexNum,arcNum;//圖中當前的頂點數和邊數 }MGraph; //建立無向網圖的鄰接矩陣表示 void CreateMGraph(MGraph *G) { int
i,j,k,w; printf("輸入頂點數和邊數(頂點數,邊數):\n"); scanf("%d,%d",&G->vexNum,&G->arcNum);//輸入頂點數和邊數 getchar(); printf("輸入頂點字元(字串形式):\n"); for(i=0;i<G->vexNum;i++)//讀入頂點資訊,建立頂點表 scanf("%c",&G->vexs[i]); for(i=0;i<G->vexNum;i++) for(j=0;j<G->vexNum;j++) G->arc[i][j]=INFINITY;//鄰接矩陣初始化
for(k=0;k<G->arcNum;k++)//讀入arcNum條邊,建立鄰接矩陣 { printf("輸入邊(vi,vj)上的頂點i,頂點j和權w:\n"); scanf("%d,%d,%d",&i,&j,&w);//輸入邊(vi,vj)上的權w G->arc[i][j]=w; G->arc[j][i] = G->arc[i][j];//因為是無向圖,矩陣對稱 } } /** * v0為任意一頂點 */ void Prim(MGraph g,int v0){ int vset[MAXVEX],lowcast[MAXVEX]; int i,j,k,sum,min; for(i=0;i<g.vexNum;++i){ // lowcast[i]儲存與當前樹相接的邊的權值 lowcast[i]=g.arc[v0][i]; vset[i]=0; } // vset[i]=1表示頂點併入生成樹中 vset[v0]=1; // 累計樹的權值 sum=0; // 從與樹相接的邊中選取一條權值最小的邊,並將與該邊連線的頂點併入樹中 for(i=0;i<g.vexNum-1;++i){ min=INFINITY; // INFINITY是已定義的比圖中所有邊權值都大的常量 for(j=0;j<g.vexNum;++j){ // 如果頂點已在樹中,則不對其進行操作 // 找到權值最小的邊及其所連線的頂點 if(vset[j]==0&&lowcast[j]<min){ min=lowcast[j]; k=j; } } vset[k]=1; sum+=min; for(j=0;j<g.vexNum;++j){ // 對當前生成樹中的頂點的相接的邊進行比較,更新與剩餘頂點的邊的最小權值 if(vset[j]==0&&g.arc[k][j]<lowcast[j]){ lowcast[j]=g.arc[k][j]; } } } printf("最小權值之和:%d\n",sum); } int main() { MGraph G; CreateMGraph(&G); Prim(G,0); return 0; }