資料結構——Prim演算法
阿新 • • 發佈:2018-11-30
Prim演算法(加點法)
- Prim為求圖最小生成樹的演算法
- 本文章採用鄰接矩陣的儲存方式
具體思路如下
- 1.首先以鄰接矩陣方式輸入圖
- 2.進入演算法函式
- 3.設定closedge陣列輔助
- 4.先將一個start頂點加入生成樹頂點集合中
- 5.用start頂點的邊關係將closedge陣列初始化
- 6.找出當前closedge沒有進入生成樹的頂點中lowcost最小值記為min,對應的頂點記為m
- 7.將m頂點加入到生成樹頂點集合中
- 8.列印剛加入的頂點與權值最小邊的資訊
- 9.用m頂點的資訊更新closedge陣列的資訊,如果發現更小的權值邊出現,則替換原有資訊
- 10.重複6-9直到找出n-1條邊是結束
具體程式碼如下
/*prim演算法(加點法),適合稠密圖*/ #include<stdio.h> #include<stdlib.h> #define MAXVEX 20 /*最大頂點個數*/ #define INFINITY 32767 /*表示無窮,可自定義*/ #define Elem int #define FALSE 0 #define OK 1 #define TRUE 1 typedef char VertexType; typedef struct{ int arcs[MAXVEX][MAXVEX]; //鄰接矩陣,邊的資訊 VertexType vexs[MAXVEX]; //頂點資訊 int vexnum; //頂點數目 int arcnum; //邊(弧)數目 }AdjMatrix; typedef struct{ //陣列元素的下標對應圖G的頂點序號 int adjvex; /*記錄該頂點和頂點集合中相連權值最小的頂點序號*/ int lowcost; /*記錄最小的權值*/ }Closedge; //根據名稱得到指定頂點在頂點集合中的下標 int getIndexOfVexs(char vex,AdjMatrix *MG) { for(int i=1;i<=MG->vexnum;i++) { if(MG->vexs[i]==vex) return i; } return 0; } //用鄰接矩陣建立圖 void Create(AdjMatrix *MG){ int v1,v2; char c1,c2; printf("請輸入頂點數目: "); //輸入頂點數 scanf("%d",&MG->vexnum); printf("請輸入邊的數目: "); //輸入邊數 scanf("%d",&MG->arcnum); getchar(); //輸入各頂點資訊 for(int i=1;i<=MG->vexnum;i++) { printf("請輸入第%d個頂點(char): ",i); //請輸入各頂點資訊 scanf("%c",&MG->vexs[i]); getchar(); } //初始化鄰接矩陣 for(int i=1;i<=MG->vexnum;i++) for (int j=1;j<=MG->vexnum;j++) MG->arcs[i][j]=INFINITY; /*如果是網則賦值INFINITY */ //輸入邊的資訊,建立鄰接矩陣 for(int k=1;k<=MG->arcnum;k++) { printf("請輸入第%d個邊連線的兩個頂點及權值v1(char) v2(char) weight(int): ",k); //請輸入有關係的兩個頂點 int weight=INFINITY; scanf("%c %c %d",&c1,&c2,&weight); v1=getIndexOfVexs(c1,MG); v2=getIndexOfVexs(c2,MG); MG->arcs[v1][v2]=weight; MG->arcs[v2][v1]=weight; //無向圖為對稱矩陣 getchar(); } } //列印圖的資訊 void Printf(AdjMatrix MG) { printf("頂點數目為: %d\n",MG.vexnum); printf("邊的數目為: %d\n",MG.arcnum); printf("頂點: "); for(int i=1;i<=MG.vexnum;i++) printf("%c",MG.vexs[i]); printf("\n鄰接矩陣為: \n"); for(int i=1;i<=MG.vexnum;i++) { for(int j=1;j<=MG.vexnum;j++){ if(MG.arcs[i][j]==INFINITY) printf("#"); else printf("%d",MG.arcs[i][j]); } printf("\n"); } } /****************最小生成樹(Prim演算法)***************/ void Prim(AdjMatrix G,int start){ Closedge closedge[MAXVEX]; closedge[start].lowcost=0; /*標誌頂點加入到生成樹集合中*/ //初始化剩下的所有頂點對應的closedge陣列 for(int i=1;i<=G.vexnum;i++){ if(i!=start){ closedge[i].adjvex=start; closedge[i].lowcost=G.arcs[start][i]; } } printf("\n最小生成樹的生成過程:"); //從邊集中選出n-1條符合條件的邊 for(int e=1;e<=G.vexnum-1;e++){ int m; //記錄頂點 int min=INFINITY; //記錄最小權值 //找出當前closedge沒有進入生成樹的頂點中lowcost最小值對應的頂點 for(int k=1;k<=G.vexnum;k++){ if((closedge[k].lowcost!=0)&&closedge[k].lowcost<min){ min=closedge[k].lowcost; m=k; } } printf("\n(%c,%c) %d",G.vexs[closedge[m].adjvex],G.vexs[m],min); closedge[m].lowcost=0; /*標誌頂點m進入生成樹集合*/ //用新的生成樹頂點m,更新closedge陣列 for(int i=1;i<=G.vexnum;i++){ if((closedge[i].lowcost!=0)&&G.arcs[m][i]<closedge[i].lowcost){ //如果發現有更小的權值邊出現,則替換原有資訊 closedge[i].lowcost=G.arcs[m][i]; closedge[i].adjvex=m; } } } } int main(){ AdjMatrix MG,T; Create(&MG); Prim(MG,1); return 0; }