贪心策略之最小生成树中的kruskal 算法
2013-11-19 22:54
399 查看
在算法设计里面一个重要的策略就是贪心算法。贪心算法较之于动态规划是每一步求得的解是当前局部最优的解,这样一步步求下去那么所得到的解就会无限接近于全局的最优解,在某些情况下会等于最优解。
在这里主要谈谈贪心策略中的最小生成树。在嵌入式设计中,我们都会用线将各个component 连接起来,这里我们要保证每一个component 的每一个针脚我们都必须连上,这里做一个合理的假设,假设图论中的每一个节点就是component的针脚,而edge 就是连接的线,每一个线的长度和绕度等一些cost 则将它置为权重 w. 那么实际上我们已经把连接component的问题成功转化成了图论中节点、边和权重的问题了。 我们希望找到一个无环子集T(属于边集),即能够将所有的节点(针脚)连接起来,又具有最小的权重,由于子集T 是无环的,并且连接所有的节点,那么T 必然就是一个树。于是我们将由图生成的树称之为最小生成树。
而如何来生成这个树就是我接下来要讲的问题了。
假设集合A 是某颗最小生成树的一个子集,我们要做的事情就是选择一条连接2个节点边edge,将其加入到A 中,使得加入元素之后的A 依旧是某棵最小生成树的子集,由于我们可以将这条边安全的加入到子集A 中,那么称这样的边为安全边。现在剩下的就是辨别哪条边是安全边了。我们先看下图:
无向图G 的一个切割(S, V-S)是集合V 的一个划分,如果一条边的一个端点位于集合S, 而另一条边位于集合V-S,则称这条边横跨切割(S,V-S), 如果最小生成树集合A不存在横跨该切割的边,则称该切割尊重集合A 。在横跨一个切割的所有边中,权重最小的边称为轻量级边。
那么我们可以得出安全边的四个条件:
一:G 是连通无向图
二:A 包括在某棵最小生成树中
三:(S, V-S)是尊重集合A 的任意一个切割
四:边e 是横跨切割的一条轻量级边
结论:边e 是安全的
辨别安全边的理论已经分析完,那么我们下一步就是找出安全边了,在这里介绍kruskal 理论。
Kruskal理论认为将每一个结点看成是一个最小生成树,每次从图中找出权重最小的边,检查边两头的结点,如果结点分属于两个不同的集合,那么就进行合并操作,直到所有的边检测完。
在这里主要谈谈贪心策略中的最小生成树。在嵌入式设计中,我们都会用线将各个component 连接起来,这里我们要保证每一个component 的每一个针脚我们都必须连上,这里做一个合理的假设,假设图论中的每一个节点就是component的针脚,而edge 就是连接的线,每一个线的长度和绕度等一些cost 则将它置为权重 w. 那么实际上我们已经把连接component的问题成功转化成了图论中节点、边和权重的问题了。 我们希望找到一个无环子集T(属于边集),即能够将所有的节点(针脚)连接起来,又具有最小的权重,由于子集T 是无环的,并且连接所有的节点,那么T 必然就是一个树。于是我们将由图生成的树称之为最小生成树。
而如何来生成这个树就是我接下来要讲的问题了。
假设集合A 是某颗最小生成树的一个子集,我们要做的事情就是选择一条连接2个节点边edge,将其加入到A 中,使得加入元素之后的A 依旧是某棵最小生成树的子集,由于我们可以将这条边安全的加入到子集A 中,那么称这样的边为安全边。现在剩下的就是辨别哪条边是安全边了。我们先看下图:
无向图G 的一个切割(S, V-S)是集合V 的一个划分,如果一条边的一个端点位于集合S, 而另一条边位于集合V-S,则称这条边横跨切割(S,V-S), 如果最小生成树集合A不存在横跨该切割的边,则称该切割尊重集合A 。在横跨一个切割的所有边中,权重最小的边称为轻量级边。
那么我们可以得出安全边的四个条件:
一:G 是连通无向图
二:A 包括在某棵最小生成树中
三:(S, V-S)是尊重集合A 的任意一个切割
四:边e 是横跨切割的一条轻量级边
结论:边e 是安全的
辨别安全边的理论已经分析完,那么我们下一步就是找出安全边了,在这里介绍kruskal 理论。
Kruskal理论认为将每一个结点看成是一个最小生成树,每次从图中找出权重最小的边,检查边两头的结点,如果结点分属于两个不同的集合,那么就进行合并操作,直到所有的边检测完。
#include <stdio.h> #include <stdlib.h> #define MAX 100 struct Vertex{ char data; int rank; struct Vertex *parent; }; typedef struct{ struct Vertex *u; struct Vertex *v; int w; }Edge; struct Vertex vertex[MAX]; Edge edge[MAX]; /* 文件中的测试数据:注意数据的格式和函数getdata 中输入格式的匹配 7 ABCDEFG 11 AB 7 AD 5 BC 8 BD 9 BE 7 CE 5 DE 15 DF 6 EF 8 EG 9 FG 11 */ // return n is sum of edges int GetData() { int i ,n; char ch, ch2; FILE *fin ; fin = fopen("data.txt", "rb"); // 文件中第一个数据是节点的总数 n fscanf(fin, "%d\n", &n); for(i=0; i < n; i++) { fscanf(fin, "%c", &vertex[i].data); vertex[i].rank = 0; vertex[i].parent = &vertex[i]; } // 随后输入的是边的总数 n fscanf(fin, "%d\n", &n);// n is edge of sum for(i=0; i < n; i++) { fscanf(fin, "%c%c%d\n", &ch, &ch2, &edge[i].w); edge[i].u = &vertex[ch-'A']; edge[i].v = &vertex[ch2-'A']; } fclose(fin); return n; } int cmp(const Edge *a, const Edge *b) { return (*a).w - (*b).w; } struct Vertex* Find_set(struct Vertex *x) { if(x != x->parent) x->parent = Find_set(x->parent); return x->parent; } void Link(struct Vertex *x,struct Vertex *y) { if(x->rank > y->rank) y->parent = x; else { x->parent = y; if(x->rank==y->rank) y->rank ++; } } void Union(struct Vertex *x, struct Vertex *y) { Link(Find_set(x), Find_set(y)); } void Kruskal(int n) { int i; qsort(edge, n, sizeof(Edge), cmp); for(i = 0; i < n; i++) { if(Find_set(edge[i].u) != Find_set(edge[i].v)) { printf("%c --- %c : %d \n", edge[i].u->data, edge[i].v->data, edge[i].w); Union(edge[i].u, edge[i].v); } } } int main() { Kruskal(GetData()); system("pause"); return 0; }
相关文章推荐
- 贪心生成最小生成树-克鲁斯卡尔(Kruskal)算法(归并排序)(并查集)
- 图论;最小生成树;普利姆算法;贪心策略;可用最小堆实现;
- 最小生成树(Kruskal算法)贪心算法 利用并查集
- 分量算法poj 1751 Highways 最小生成树之Kruskal(克鲁斯卡尔)算法
- 图的广度遍历、深度遍历及最小生成树书算法(Prim、Kruskal)
- network 最小生成树 Kruskal 算法 poj 1861 zoj 1542
- 算法记录---最小生成树【kruskal&&prim】
- 贪心算法——Prim最小生成树
- 贪心算法基础之最小生成树 51nod Kruskal算法
- 算法:图解最小生成树之克鲁斯卡尔(Kruskal)算法
- 图解最小生成树 - 克鲁斯卡尔(Kruskal)算法
- Num 32 : HDOJ : 1233 还是畅通工程 [ kruskal( 克鲁斯卡尔 )算法 ] [ 最小生成树 ]
- 克鲁斯卡尔(Kruskal)算法求解最小生成树
- [算法系列之二十七]Kruskal最小生成树算法
- 数据结构 学习笔记(九):图(下):最小生成树(Prim,Kruskal 算法),拓扑排序 AOV,关键路径 AOE
- 最小生成树——克鲁斯卡尔(Kruskal)算法
- 最小生成树算法 :Prim算法 和 Kruskal 算法
- 贪心算法之Prim最小生成树
- hdu 1233 还是畅通工程(最小生成树的Prim和Kruskal两种算法的c++实现)(prim算法详解)
- 关于图的常用算法——Dijkstra单源最短路径、Floyd多源最短路径、Prim和Kruskal最小生成树算法