最小生成树

Prim算法

Prim算法是一种产生最小生成树的算法。该算法于1930年由捷克数学家沃伊捷赫·亚尔尼克(英语:Vojtěch Jarník)发现;并在1957年由美国计算机科学家罗伯特·普里姆(英语:Robert C. Prim)独立发现;1959年,艾兹格·迪科斯彻再次发现了该算法。

Prim算法从任意一个顶点开始,每次选择一个与当前顶点集最近的一个顶点,并将两顶点之间的边加入到树中。Prim算法在找当前最近顶点时使用到了贪婪算法。

算法描述:
1. 在一个加权连通图中,顶点集合V,边集合为E
2. 任意选出一个点作为初始顶点,标记为visit,计算所有与之相连接的点的距离,选择距离最短的,标记visit.
3. 重复以下操作,直到所有点都被标记为visit
在剩下的点钟,计算与已标记visit点距离最小的点,标记visit,证明加入了最小生成树。

下面我们来看一个最小生成树生成的过程:
1 起初,从顶点a开始生成最小生成树
这里写图片描述
2 选择顶点a后,顶点啊置成visit(涂黑),计算周围与它连接的点的距离:
这里写图片描述
3 与之相连的点距离分别为7,6,4,选择C点距离最短,涂黑C,同时将这条边高亮加入最小生成树:
这里写图片描述
4 计算与a,c相连的点的距离(已经涂黑的点不计算),因为与a相连的已经计算过了,只需要计算与c相连的点,如果一个点与a,c都相连,那么它与a的距离之前已经计算过了,如果它与c的距离更近,则更新距离值,这里计算的是未涂黑的点距离涂黑的点的最近距离,很明显,ba7bc的距离为6,更新b和已访问的点集距离为6,而f,ec的距离分别是8,9,所以还是涂黑b,高亮边bc
这里写图片描述
5 接下来很明显,d距离b最短,将d涂黑,bd高亮:
这里写图片描述
f距离d7,距离b4,更新它的最短距离值是4,所以涂黑f,高亮bf
这里写图片描述
7 最后只有e了:
这里写图片描述

针对如上的图,代码实例如下:

?
[cpp]  view plain  copy
  1. #include<iostream>  
  2. #define INF 10000  
  3. using namespace std;  
  4. constint N = 6;  
  5. bool visit[N];  
  6. intdist[N] = { 0, };  
  7. intgraph[N][N] = { {INF,7,4,INF,INF,INF},  //INF代表两点之间不可达  
  8.                     {7,INF,6,2,INF,4},  
  9.                     {4,6,INF,INF,9,8},  
  10.                     {INF,2,INF,INF,INF,7},  
  11.                     {INF,INF,9,INF,INF,1},  
  12.                     {INF,4,8,7,1,INF}  
  13.                   };  
  14. intprim(intcur)  
  15. {  
  16.     intindex = cur;  
  17.     intsum = 0;  
  18.     inti = 0;  
  19.     intj = 0;  
  20.     cout << index << " ";  
  21.     memset(visit,falsesizeof(visit));  
  22.     visit[cur] = true;  
  23.     for(i = 0; i < N; i++)  
  24.         dist[i] = graph[cur][i];//初始化,每个与a邻接的点的距离存入dist  
  25.     for(i = 1; i < N; i++)  
  26.     {  
  27.         intminor = INF;  
  28.         for(j = 0; j < N; j++)  
  29.         {  
  30.             if(!visit[j] && dist[j] < minor)          //找到未访问的点中,距离当前最小生成树距离最小的点  
  31.             {  
  32.                 minor = dist[j];  
  33.                 index = j;  
  34.             }  
  35.         }  
  36.         visit[index] = true;  
  37.         cout << index << " ";  
  38.         sum += minor;  
  39.         for(j = 0; j < N; j++)  
  40.         {  
  41.             if(!visit[j] && dist[j]>graph[index][j])      //执行更新,如果点距离当前点的距离更近,就更新dist  
  42.             {  
  43.                 dist[j] = graph[index][j];  
  44.             }  
  45.         }  
  46.     }  
  47.     cout << endl;  
  48.     returnsum;               //返回最小生成树的总路径值  
  49. }  
  50. intmain()  
  51. {  
  52.     cout << prim(0) << endl;//从顶点a开始  
  53.     return0;  
  54. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值