当前位置:   article > 正文

数据结构—图—最小生成树_数据结构最小生成树

数据结构最小生成树

什么是最小生成树

一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边。 [1]  最小生成树可以用kruskal(克鲁斯卡尔)算法或prim(普里姆)算法求出。 

 

2、普里姆算法—Prim算法

算法思路:
首先就是从图中的一个起点a开始,把a加入U集合,然后,寻找从与a有关联的边中,权重最小的那条边并且该边的终点b在顶点集合:(V-U)中,我们也把b加入到集合U中,并且输出边(a,b)的信息,这样我们的集合U就有:{a,b},然后,我们寻找与a关联和b关联的边中,权重最小的那条边并且该边的终点在集合:(V-U)中,我们把c加入到集合U中,并且输出对应的那条边的信息,这样我们的集合U就有:{a,b,c}这三个元素了,一次类推,直到所有顶点都加入到了集合U。

下面我们对下面这幅图求其最小生成树:

这里写图片描述

假设我们从顶点v1开始,所以我们可以发现(v1,v3)边的权重最小,所以第一个输出的边就是:v1—v3=1:
这里写图片描述

然后,我们要从v1和v3作为起点的边中寻找权重最小的边,首先了(v1,v3)已经访问过了,所以我们从其他边中寻找,发现(v3,v6)这条边最小,所以输出边就是:v3—v6=4
这里写图片描述

然后,我们要从v1、v3、v6这三个点相关联的边中寻找一条权重最小的边,我们可以发现边(v6,v4)权重最小,所以输出边就是:v6—v4=2.
这里写图片描述

然后,我们就从v1、v3、v6、v4这四个顶点相关联的边中寻找权重最小的边,发现边(v3,v2)的权重最小,所以输出边:v3—–v2=5
这里写图片描述

然后,我们就从v1、v3、v6、v4,v2这2五个顶点相关联的边中寻找权重最小的边,发现边(v2,v5)的权重最小,所以输出边:v2—–v5=3
这里写图片描述

最后,我们发现六个点都已经加入到集合U了,我们的最小生成树建立完成。

时间复杂度

最小边、权的数据结构时间复杂度(总计)
邻接矩阵、搜索O(N^2)
二叉堆(后文伪代码中使用的数据结构)、邻接表O((N + E) log(N)) = O(E log(N))
斐波那契堆邻接表O(E + N log(N))

通过邻接矩阵图表示的简易实现中,找到所有最小权边共需O(V)的运行时间。使用简单的二叉堆与邻接表来表示的话,普里姆算法的运行时间则可缩减为O(ElogV),其中E为连通图的边数,V为顶点数。如果使用较为复杂的斐波那契堆,则可将运行时间进一步缩短为O(E+VlogV),这在连通图足够密集时(当E满足Ω(VlogV)条件时),可较显著地提高运行速度。 

代码实现:

  1. #define MAXN 1000
  2. #define INF 1<<30
  3. int closest[MAXN],lowcost[MAXN],m;//m为节点的个数
  4. int G[MAXN][MAXN];//邻接矩阵
  5. int prim()
  6. {
  7. for(int i=0; i<m; i++)
  8. {
  9. lowcost[i]=INF;
  10. }
  11. for(int i=0; i<m; i++)
  12. {
  13. closest[i]=0;
  14. }
  15. closest[0]=-1;//加入第一个点,-1表示该点在集合U中,否则在集合V中
  16. int num=0,ans=0,e=0;//e为最新加入集合的点
  17. while(num<m-1)//加入m-1条边
  18. {
  19. int micost=INF,miedge=-1;
  20. for(int i=0; i<m; i++)
  21. if(closest[i]!=-1)
  22. {
  23. int temp=G[e][i];
  24. if(temp<lowcost[i])
  25. {
  26. lowcost[i]=temp;
  27. closest[i]=e;
  28. }
  29. if(lowcost[i]<micost)
  30. micost=lowcost[miedge=i];
  31. }
  32. ans+=micost;
  33. closest[e=miedge]=-1;
  34. num++;
  35. }
  36. return ans;
  37. }

应用实例:畅通工程之局部最小花费问题

 

Kruskal—克鲁斯卡算法

算法思路:
(1)将图中的所有边都去掉。
(2)将边按权值从小到大的顺序添加到图中,保证添加的过程中不会形成环
(3)重复上一步直到连接所有顶点,此时就生成了最小生成树。这是一种贪心策略。

这里同样我们给出一个和Prim算法讲解中同样的例子,模拟克鲁斯卡算法生成最小生成树的详细的过程:

首先完整的图如下图:
这里写图片描述

然后,我们需要从这些边中找出权重最小的那条边,可以发现边(v1,v3)这条边的权重是最小的,所以我们输出边:v1—-v3=1
这里写图片描述

然后,我们需要在剩余的边中,再次寻找一条权重最小的边,可以发现边(v4,v6)这条边的权重最小,所以输出边:v4—v6=2
这里写图片描述

然后,我们再次从剩余边中寻找权重最小的边,发现边(v2,v5)的权重最小,所以可以输出边:v2—v5=3,
这里写图片描述

然后,我们使用同样的方式找出了权重最小的边:(v3,v6),所以我们输出边:v3—v6=4
这里写图片描述

好了,现在我们还需要找出最后一条边就可以构造出一颗最小生成树,但是这个时候我们有三个选择:(v1,V4),(v2,v3),(v3,v4),这三条边的权重都是5,首先我们如果选(v1,v4)的话,得到的图如下:
这里写图片描述
我们发现,这肯定是不符合我们算法要求的,因为它出现了一个环,所以我们再使用第二个(v2,v3)试试,得到图形如下:
这里写图片描述

我们发现,这个图中没有环出现,而且把所有的顶点都加入到了这颗树上了,所以(v2,v3)就是我们所需要的边,所以最后一个输出的边就是:v2—v3=5
 

  1. #include<iostream>
  2. #include<queue>
  3. using namespace std;
  4. struct EdgeNode
  5. {
  6. int v1;
  7. int v2;
  8. int value;
  9. bool operator<(const EdgeNode &a) const
  10. {
  11. return a.value<value;
  12. }
  13. };
  14. int *root;
  15. priority_queue<EdgeNode> pq;
  16. int Find(int x)
  17. {
  18. int i=x;
  19. while(i!=root[i])
  20. i=root[i];
  21. while(i!=root[x])
  22. {
  23. temp=root[x];
  24. root[x]=i;
  25. x = temp;
  26. }
  27. return i;
  28. }
  29. void Union(int a,int b)
  30. {
  31. a=Find(a);
  32. b=Find(b);
  33. if(a!=b)
  34. root[a]=b;
  35. }
  36. void Kruskal()
  37. {
  38. EdgeNode b;
  39. cout<<"加入最小生成树中的边依次为: "<<endl;
  40. while(!pq.empty())
  41. {
  42. b=pq.top();
  43. pq.pop();
  44. if(Find(b.v1)!=Find(b.v2))
  45. {
  46. cout<<b.v1<<"----"<<b.v2<<endl;
  47. Union(b.v1,b.v2);
  48. }
  49. }
  50. }
  51. void main()
  52. {
  53. int n=0;
  54. int m=0;
  55. cout<<"请输入图中点的个数: "<<endl;
  56. cin>>n;
  57. root=new int [n+1];
  58. for(int i=1; i<=n; i++)
  59. root[i]=i;
  60. cout<<"请输入图中边的条数: "<<endl;
  61. cin>>m;
  62. EdgeNode a;
  63. cout<<"请依次输入每条边的两个顶点及其权重: "<<endl;
  64. while(m--)
  65. {
  66. cin>>a.v1>>a.v2>>a.value;
  67. pq.push(a);
  68. }
  69. Kruskal();
  70. }

实例:畅通工程之最低成本建设问题  

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/243429
推荐阅读
相关标签
  

闽ICP备14008679号