[算法]最小生成树-kruskal算法

[算法]最小生成树-kruskal算法

很久以前已经接触过论的一些基本算法的,但是未曾亲自实现,只是了解一下原理,近期有空,开始对于图论算法整理。

在此kruskal算法中,用到并查集数据结构,并查集这个内容在博文[数据结构]并查集中有所介绍。

kruskal是一个贪心的算法,S为入选集,记录已经并入最小生成树中的边,Q为候选集,记录是待检查是否可并入最小生成树的边,m为总顶点数

1、从Q中选出一条边权值最小的边e

2、判断e加入S后是否使得S构成回路,若构成回路,则将e从Q剔除,以后不用再访问,再转向1,如果不构成回路,转向3

3、e加入S后,如果当前S中的边数目是总顶点数m-1,则已经找到最小生成树,退出循环,否则转向1继续寻找下一条合符条件的边

算法实现如下:

 1 #include <iostream>

 2 #include <algorithm>

 3 using namespace std;

 4 const int maxSize = 100;

 5 typedef struct edge{//由kruskal算法可知,它是对边权值进行比较的,

 6                     //所以我们不适用邻接矩阵来表示图, 使用边的数据结构来表示图 

 7     int startPoint,endPoint;

 8     int length;

 9 }edge;

10 bool cmp(edge e1, edge e2){

11     return e1.length < e2.length;

12 }

13 void makeSet(int* a, int n){

14     for(int i = 0; i < n; ++i){

15         a[i] = i;

16     }

17 }

18 int find(int* a, int x){

19     if(x == a[x]){

20         return x;

21     }

22     else{

23         return a[x] = find(a,a[x]);

24     }

25 }

26 void unionSet(int* a,int x, int y){

27     if(a[x] != a[y]){

28         a[find(a,y)] = find(a,x);

29     }

30 }

31 int kruskal(edge* e, int n,int* a, int m){//m为顶点个数,n为边条数 

32     sort(e,e+n,cmp); //sort是标准库algorithm中的函数,使得按权值上升 

33     int i;

34     makeSet(a,m);

35     int sum = e[0].length;//初始化S,里面第一条边肯定是权值最小的边 

36     unionSet(a,e[0].startPoint,e[0].endPoint);//把S中相互可达的顶点合到同一个组 

37     int j = 1;

38     for(i = 1; j < m-1 && i < n; ++i){

39         if( find(a,0)!=find(a,i) ){ 

40         //当e[i]的两个顶点在S中是不可达的,表示两个顶点在S中的不同组里面,

41         //则加入e[i]不会有回路产生,只会把组合并 

42         //(注意,同一个顶点可以在不同的边上)

43             unionSet(a,e[i].startPoint,e[i].endPoint);

44             sum += e[i].length;

45             ++j;

46         }

47     }

48     return sum;

49 }

50 int main(int argc, char**){

51     const int infinite = 9999;

52     int map[maxSize][maxSize]={{0,5,infinite,infinite,7},

53                                 {5,0,4,2,infinite},

54                                 {infinite,4,0,6,8},

55                                 {infinite,2,6,0,1},

56                                 {7,infinite,8,1,0}};

57     edge e[maxSize];

58     int a[maxSize];

59     int i,j;

60     int m = 5,n=0;

61     for(i = 0; i < m; ++i){

62         for(j = i+1; j < m; ++j){

63             if(map[i][j] < infinite){

64                 e[n].startPoint = i;

65                 e[n].endPoint = j;

66                 e[n++].length = map[i][j]; 

67             }

68         }

69     }

70     cout<<kruskal(e,n,a,m);

71 }

 


本文基于知识共享署名-非商业性使用 3.0 许可协议进行许可。欢迎转载、演绎,但是必须保留本文的署名林羽飞扬,若需咨询,请给我发信

你可能感兴趣的:(最小生成树)