Kruskal最小生成树
Kruskal算法似乎更加贴近贪心算法。
每次都从边集中找出权值最小的边,符合条件则组成一个小的树。
最终这些小的树会合并成最后的大树,也就是我们想要得到的生成树。
Kruskal算法需要用到两种数据结构:最小堆、并查集
初始化:
所以节点都是一棵树,相当于初始化并查集。
将所有边都加入到最小堆中。
(1)从最小堆中选出一个权值最小的边, 将此边删除。
如果这个边的相连的两个节点在同一个集合中,
· continue
如果不在同一集合中,将两个节点加入到同一集合。
(2)循环直到count==n-1 或 最小堆中没有元素
typedef int Vertex; typedef int Weight; typedef struct ArcNode { Vertex to; Vertex from; int Weight; strcut ArcNode *next; }ArcNode; typedef struct VNode { Vertex id; ArcNode *first; }VNode; typedef struct LGraph { VNode* Aject[MaxVertexNum]; int v, e; }LGraph; void Kruskal(LGraph& G) { //自定义最小堆 privority_queue q; //将边加入最小堆中 for(int i = 0; i < G.v; i++) { for(ArcNode* a = G.Aject[i].first; a != NULL; a = a->next) { q.push(a); } } //初始化并查集 int d[G.v]; init(G.v, d); int count = 0; while(count < n-1 && !q.empty()) { ArcNode* a = q.pop(); int from = a.from; int to = a.to; if(find(from) == find(to)) continue; else { union(from, to); count++; } } } void init(int n, int d[]) { for(int i = 0; i < n; i++) { d[i] = i; } } int find(int d[], int a) { if(d[a] == a) return a; else d[a] = find(d[a]); return d[a]; } void union(int d[], int a, int b) { if(find(a) == find(b)) return ; else d[a] = find(b); }