【演算法筆記】普里姆Prim演算法的簡單實現
阿新 • • 發佈:2019-01-07
前言
由於最近在學習資料結構,在學習的過程中動手把演算法的思路用程式碼的形式實現了,這樣記憶更深刻。所以在此記錄下學習普里姆演算法時,如何通過該演算法獲得連通網的最小生成樹。
演算法實現思路
一、建立以鄰接矩陣為儲存方式的帶權連通無向圖(連通網)
二、利用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;
}