最小生成樹之Prim演算法
阿新 • • 發佈:2020-08-10
生成樹
一個連通圖的生成樹是一個極小連通子圖,它含有圖中全部n個頂點和構成一棵樹的(n-1)條邊。
- 連通圖由一次遍歷就可以產生生成樹
- 由深度優先遍歷得到的生成樹稱為深度優先生成樹。
- 由廣度優先遍歷得到的生成樹稱為廣度優先生成樹。
一個連通圖的生成樹不一定是唯一的!
最小生成樹
對於帶權連通圖G (每條邊上的權均為大於零的實數),可能有多棵不同生成樹。
每棵生成樹的所有邊的權值之和可能不同。
其中權值之和最小的生成樹稱為圖的最小生成樹。
Prim演算法
普里姆(Prim)演算法是一種構造性演算法,用於構造最小生成樹。過程如下:
- 初始化U={v}。v到其他頂點的所有邊為候選邊;
- 重複以下步驟n-1次,使得其他n-1個頂點被加入到U中:
- 從候選邊中挑選權值最小的邊輸出,設該邊在V-U中的頂點是k,將k加入U中;
- 考察當前V-U中的所有頂點j,修改候選邊:若(j,k)的權值小於原來和頂點k關聯的候選邊,則用(k,j)取代後者作為候選邊。
程式碼
Prim 演算法構造生成樹
//Prim 演算法構造生成樹 void Prim(MatGraph g, int v) { int lowcost[MAXV];//儲存權值 int MIN; int closest[MAXV], i, j, k; //closet是用來儲存與它相鄰的節點的 for (i = 0; i < g.n; i++) { lowcost[i] = g.edges[v][i]; //初始化 closest[i] = v; } for (i = 1; i < g.n; i++) { MIN = INF; for (j = 0; j < g.n; j++) if (lowcost[j] != 0 && lowcost[j] < MIN) { MIN = lowcost[j]; k = j; //記錄最近的節點的編號 } printf("邊(%d,%d)權為:%d\n", closest[k], k, MIN); lowcost[k] = 0; for (j = 0; j < g.n; j++) if (lowcost[j] != 0 && g.edges[k][j] < lowcost[j]) //尋找有沒有比較小的邊 { lowcost[j] = g.edges[k][j]; closest[j] = k; } } }
測試程式碼
# include <stdio.h> # include <stdlib.h> #define ElemType int #define maxsize 100 #define InfoType int #define MAXV 100 #define MaxSize 100 #define INF 214748364 #define INFINITE INF //鄰接矩陣的資料型別 typedef struct s { int no; //頂點編號 InfoType info;//頂點的其他資訊 } VertexType; //頂點的型別 typedef struct SS { int edges[MAXV][MAXV]; //鄰接矩陣的陣列 int n, e; //圖的頂點數和邊數 VertexType vexs[MAXV]; //存放頂點資訊 } MatGraph; /////////////////////////////////////////////////// //Prim 演算法構造生成樹 void Prim(MatGraph g, int v) { int lowcost[MAXV]; int MIN; int closest[MAXV], i, j, k; for (i = 0; i < g.n; i++) { lowcost[i] = g.edges[v][i]; //init closest[i] = v; } for (i = 1; i < g.n; i++) { MIN = INF; for (j = 0; j < g.n; j++) if (lowcost[j] != 0 && lowcost[j] < MIN) { MIN = lowcost[j]; k = j; //記錄最近的節點的編號 } printf("邊(%d,%d)權為:%d\n", closest[k], k, MIN); lowcost[k] = 0; for (j = 0; j < g.n; j++) if (lowcost[j] != 0 && g.edges[k][j] < lowcost[j]) { lowcost[j] = g.edges[k][j]; closest[j] = k; } } } ////////////////////////////////////////////////////////////// void InitMatGraph(MatGraph & g, int a[][MAXV], int n, int e) { int i, j; g.n = n; g.e = e; for(i = 0; i< n; i++) for(j = 0; j < n; j++) g.edges[i][j] = a[i][j]; } int main () { //注意無向帶權圖i=j是為0 int a[4][MAXV] = {{0, 1, 3, 1}, {1, 0, 2, 4}, {3, 2, 0, INF}, {1, 4, INF, 0}}; MatGraph g; InitMatGraph(g, a, 4, 5); Prim(g, 0); return 0; }
測試結果