使用MapReduce实现定图的最小生成树
如何实现计算最小生成树
什么是最小生成树
在一给定的无向图G = (V, E) 中,(u, v) 代表连接顶点 u 与顶点 v 的边(即),而 w(u, v) 代表此边的权重,若存在 T 为 E 的子集(即)且为无循环图,使得
w ( T ) = ∑ ( u , v ) ∈ t w ( u , v ) w(T) = \sum_{(u,v)\in t} w(u,v) w(T)=(u,v)∈t∑w(u,v)
的 w(T) 最小,则此 T 为 G 的最小生成树。
简单来说,就是在一个具有N个顶点的带权连通图G中,如果存在某个子图G’,其包含了图G中的所有顶点和一部分边,且不形成回路,并且子图G’的各边权值之和最小,则称G’为图G的最小生成树。
最小生成树其实是最小权重生成树的简称
最小生成树的性质
- 最小生成树不能有回路。
- 最小生成树可能是一个,也可能是多个。
- 最小生成树边的个数等于顶点的个数减一。
使用Kruskal
算法实现最小生成树
克鲁斯卡尔算法的核心思想是:在带权连通图中,不断地在边集合中找到最小的边,如果该边满足得到最小生成树的条件,就将其构造,直到最后得到一颗最小生成树。
Kruskal算法简述
假设 WN=(V,{E}) 是一个含有 n 个顶点的连通网,则按照克鲁斯卡尔算法构造最小生成树的过程为:先构造一个只含 n 个顶点,而边集为空的子图,若将该子图中各个顶点看成是各棵树上的根结点,则它是一个含有 n 棵树的一个森林。之后,从网的边集 E 中选取一条权值最小的边,若该条边的两个顶点分属不同的树,则将其加入子图,也就是说,将这两个顶点分别所在的两棵树合成一棵树;反之,若该条边的两个顶点已落在同一棵树上,则不可取,而应该取下一条权值最小的边再试之。依次类推,直至森林中只有一棵树,也即子图中含有 n-1条边为止。
实现逻辑
- 将所有的边根据距离由小到大排序
- 先选择最小的一条边作为初始树,并且将这条边的两个点记录至
Set集合
- 继续选择第二条边最小边(如果有两条相等的边,则随机选一条)从第二条边开始,选择时需做判断,判断规则:
- 将该边加入后,是否会形成闭环。如果形成闭环则直接跳过。
- 如果没形成闭环,就判断两个点是否在
Set集合中
,·出现过的则不记录,没有出现过的就新增进去,并将权值(距离)记录。
- 重复第3步,直到遍历完所有的边。
MapReduce实现Kruskal
算法
数据格式
点1 点2 权值(距离)
完整代码
- MyMapReduce.java
public class MyMapReduce {
static double sum = 0D;
public static void main(String[] args) {
Configuration conf = new Configuration();
Job job = null;
try {
job = Job.getInstance(conf, "MyFirstJob");
} catch (IOException e) {
e.printStackTrace();
}
//作业以jar包形式 运行
job.setJarByClass(MyMapReduce.class)