1. 程式人生 > >數據結構之最小生成樹(普裏姆算法)

數據結構之最小生成樹(普裏姆算法)

下一個 iostream 算法 -a mgr height 實例 AI cat

1)普裏姆算法

可取圖中任意一個頂點v作為生成樹的根,之後若要往生成樹上添加頂點w,則在頂點v和頂點w之間必定存在一條邊,並且

該邊的權值在所有連通頂點v和w之間的邊中取值最小。一般情況下,假設n個頂點分成兩個集合:U(包含已落在生成樹上

的結點)和V-U(尚未落在生成樹上的頂點),則在所有連通U中頂點和V-U中頂點的邊中選取權值最小的邊。

例如:起始生成樹上面就一個頂點。為了連通兩個集合,在可選的邊中,選擇權值最小的。需要輔助數組,V-U中所有頂點。

具體實例如下圖所示:求下圖的最小生成樹

技術分享圖片

我們以a點為起始點,此時的U集合={a},V-U到U集合的路徑有a-b=4,a-c=2,取最小的a-c,所以將c點添加到U集合中,U={a,c}。

此時,V-U到U集合的路徑有b-a=4,b-c=3,取最小,更新b點到U集合的最短路徑為3,此外還有c-d=5,c-h=5,所以,取V-U到U集

合的最小值為b-c=3,將b點添加到U集合中。U={a,c,b}。此時V-U到U集合存在以下點:c-d=5,c-h=5,b-d=5(與現有的c-d=5一樣,

所以不更新,仍舊采用c-d),b-e=9,取最小的,此時可以有兩個選擇,假設選擇c-d,所以將d點添加到U集合中。U={a,c,b,d}。

此時V-U到U的路徑,因為e-d=7<e-b=9,所以e點進行更新,更新為d-e=7;同理d-h=4<c-h=5,所以點h到U的路徑更新為d-h=4。

新增加的路徑為d-f和d-g。此時選擇V-U到U集合的最短路徑為d-h=4,所以將h添加到U集合,此時U={a,c,b,d,h}。依次不斷選擇

下一個距離U集合最短路徑的點,並將其添加到U集合,直到將所以頂點添加完畢。實現過程如下圖所示:

技術分享圖片

接下來的代碼示例圖:

技術分享圖片

代碼如下:

  1 #include "stdafx.h"
  2 #include<iostream>
  3 #include<string>
  4 using namespace std;
  5 
  6 #define MaxNum 10000
  7 typedef struct
MGraph 8 { 9 string vexs[60]; 10 int arcs[100][100]; 11 int vexnum, arcum; 12 }MGraph; 13 typedef struct Closedge 14 { 15 string adjvex; 16 int lowcost; 17 }minside[100]; 18 19 int locateVex(MGraph G, string u) //返回頂點u在圖中的位置 20 { 21 for (int i = 0; i < G.vexnum; i++) 22 if (G.vexs[i] == u) 23 return i; 24 return -1; 25 } 26 27 void CreateGraphUDG(MGraph &G) //構造無向圖 28 { 29 string v1, v2; 30 int w; 31 int i, j, k; 32 cout << "請輸入頂點數和邊數:"; 33 cin >> G.vexnum >> G.arcum; 34 35 cout << "請輸入頂點:"; 36 for (i = 0; i < G.vexnum; i++) 37 cin >> G.vexs[i]; 38 39 for (i = 0; i < G.vexnum; i++) 40 for (j = 0; j < G.vexnum; j++) 41 G.arcs[i][j] = 10000; 42 43 cout << "請輸入邊和權值:" << endl; 44 for (k = 0; k < G.arcum; k++) 45 { 46 cin >> v1 >> v2 >> w; 47 i = locateVex(G, v1); 48 j = locateVex(G, v2); 49 G.arcs[i][j] = G.arcs[j][i] = w; 50 } 51 52 } 53 54 int minimum(minside sz, MGraph G) //求sz中lowcost的最小值,返回序號 55 { 56 int i = 0, j, k, min; 57 while (!sz[i].lowcost) 58 i++; 59 min = sz[i].lowcost; 60 k = i; 61 for (j = i + 1; j < G.vexnum; j++) 62 { 63 if (sz[j].lowcost > 0 && min > sz[j].lowcost) 64 { 65 min = sz[j].lowcost; 66 k = j; 67 } 68 } 69 return k; 70 } 71 72 void MiniSpanTree_PRIM(MGraph G, string u) //普裏姆算法 73 { 74 int i, j, k; 75 minside closedge; 76 k = locateVex(G, u); 77 for (j = 0; j < G.vexnum; j++) 78 { 79 closedge[j].adjvex = u; 80 closedge[j].lowcost = G.arcs[k][j]; 81 } 82 closedge[k].lowcost = 0; 83 cout << "最小生成樹各邊為:" << endl; 84 85 for (i = 1; i < G.vexnum; i++) 86 { 87 k = minimum(closedge, G); 88 cout << closedge[k].adjvex << "-" << G.vexs[k] << endl; 89 closedge[k].lowcost = 0; 90 for (j = 0; j < G.vexnum; j++) 91 { 92 if (G.arcs[k][j] < closedge[j].lowcost) 93 { 94 closedge[j].adjvex = G.vexs[k]; 95 closedge[j].lowcost = G.arcs[k][j]; 96 } 97 } 98 } 99 } 100 101 int main() 102 { 103 MGraph G; 104 CreateGraphUDG(G); 105 MiniSpanTree_PRIM(G, G.vexs[0]); 106 cout << endl; 107 return 0; 108 }

輸出結果:

技術分享圖片

關於克魯斯卡爾算法博主明天會更新,請耐心等待...

數據結構之最小生成樹(普裏姆算法)