示例:

给出各个节点到相邻节点的距离,要求算出初始节点到各个节点的最短路径。

数据:

A    (B,)    (D,)
B (C,) (D,)
C (E,)
D (B,) (C,) (E,)
E (A,) (C,)

A节点为初始节点,A到B的距离为10,A到D的距离为5。

B节点到C的距离为1,B到D的距离为2,其他类推。

MapReduce计算最短路径

Map阶段

如:

A  (B,10)  (D,5)

  =>

A  0  (B,10)  (D,5)    #A到A的最短距离为0

B  10                              #存在A到B的距离为10

D  5                                #存在A到D的距离为5

从初始节点开始,将节点到其他相连节点的距离列举出来,然后传递给reduce,找到距离最短的。

记住从初始节点开始,从A开始,找到B和D,然后再找B和D的相邻节点,依次类推,这个就是广度优先搜索。

从A节点出发,A节点没有到达的节点默认的距离为inf表示无穷大。

Reduce阶段

找到所有存在的距离中最短的,并更新记录中的最短距离。

如:针对key值为B的

B  inf  (C,1)  (D,2)       #inf为最远距离,

B  10  

=>

B  10  (C,1)  (D,2)  #A到B的最短距离为10

MapReduce过程中数据的变化:

原始数据:
A (B,) (D,)
B (C,) (D,)
C (E,)
D (B,) (C,) (E,)
E (A,) (C,) 第一次mr结果:
A (B,) (D,) #从初始节点A出发,找到A到B节点和D节点的距离
B (C,) (D,)          #找到B节点,且更新值,A到B节点目前的最短距离
C inf (E,)
D (B,) (C,) (E,) #找到D节点,且更新值,A到D节点目前的最短距离
E inf (A,) (C,) 第二次mr结果
A (B,) (D,)
B (C,) (D,)
C (E,)
D (B,) (C,) (E,)
E (A,) (C,) 第三次mr结果
A (B,) (D,)
B (C,) (D,)
C (E,)
D (B,) (C,) (E,)
E (A,) (C,) 第四次mr结果
A (B,) (D,)
B (C,) (D,)
C (E,)
D (B,) (C,) (E,)
E (A,) (C,)

接下来还要考虑,什么时候所有节点的最短距离都计算完成?

我的计算方式,假设如果所有节点没有距离进行更新,说明所有节点的最短距离都已经计算完成,则完成计算。

源代码:

RunJob.java

 import java.io.IOException;

 import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.input.KeyValueTextInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.util.StringUtils; /**
* Created by Edward on 2016/7/15.
*/
public class RunJob { static enum eInf {
COUNTER
} public static void main(String[] args) {
Configuration conf = new Configuration(); conf.set("fs.defaultFS", "hdfs://node1:8020"); try {
FileSystem fs = FileSystem.get(conf);
int i = 0;
long num = 1;
long tmp = 0;
while (num > 0) {
i++;
conf.setInt("run.counter", i);
Job job = Job.getInstance(conf);
job.setJarByClass(RunJob.class);
job.setMapperClass(ShortestPathMapper.class);
job.setReducerClass(ShortestPathReducer.class);
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(Text.class); //key value 的格式 第一个item为key,后面的item为value
job.setInputFormatClass(KeyValueTextInputFormat.class); if (i == 1)
FileInputFormat.addInputPath(job, new Path("/test/shortestpath/input/"));
else
FileInputFormat.addInputPath(job, new Path("/test/shortestpath/output/sp" + (i - 1))); Path outPath = new Path("/test/shortestpath/output/sp" + i);
if (fs.exists(outPath)) {
fs.delete(outPath, true);
}
FileOutputFormat.setOutputPath(job, outPath); boolean b = job.waitForCompletion(true); if (b) {
num = job.getCounters().findCounter(eInf.COUNTER).getValue();
if (num == 0) {
System.out.println("执行了" + i + "次,完成最短路径的计算");
}
}
} } catch (Exception e) { e.printStackTrace();
} } /**
* @author Edward
*
* @1 A (B,10) (D,5) =>
* A 0 (B,10) (D,5)
* B 10
* D 5
* @2 B 10 (C,1) (D,2) =>
* B 10 (C,1) (D,2)
* C 11
* D 13
*/
public static class ShortestPathMapper extends Mapper<Text, Text, Text, Text> { protected void map(Text key, Text value, Context context) throws IOException, InterruptedException {
int conuter = context.getConfiguration().getInt("run.counter", 1); Node node = new Node();
String distance = null;
String str = null; // 第一次计算,填写默认距离 A:0 其他:inf
if (conuter == 1) {
if (key.toString().equals("A") || key.toString().equals("1")) {
distance = "0";
} else {
distance = "inf";
}
str = distance + "\t" + value.toString();
} else {
str = value.toString();
} context.write(key, new Text(str)); node.FormatNode(str); // 没走到此节点 退出
if (node.getDistance().equals("inf"))
return; // 重新计算源点A到各点的距离
for (int i = 0; i < node.getNodeNum(); i++) {
String k = node.getNodeKey(i);
String v = new String(
Integer.parseInt(node.getNodeValue(i)) + Integer.parseInt(node.getDistance()) + "");
context.write(new Text(k), new Text(v));
}
}
} /**
* @author Edward
*
* B 10 (C,1) (D,2)
* B 8 =>
* B 8 (C,1) (D,2)
*
*/
public static class ShortestPathReducer extends Reducer<Text, Text, Text, Text> { protected void reduce(Text arg0, Iterable<Text> arg1, Context arg2) throws IOException, InterruptedException {
String min = null;
int i = 0;
String dis = "inf";
Node node = new Node();
for (Text t : arg1) {
i++;
dis = StringUtils.split(t.toString(), '\t')[0]; // 如果存在inf节点,表示存在没有计算距离的节点。
// if(dis.equals("inf"))
// arg2.getCounter(eInf.COUNTER).increment(1L); // 判断是否存在相邻节点,如果是则需要保留信息,并找到最小距离进行更新。
String[] strs = StringUtils.split(t.toString(), '\t');
if (strs.length > 1) {
node.FormatNode(t.toString());
} // 第一条数据默认是最小距离
if (i == 1) {
min = dis;
} else {
if (dis.equals("inf"))
;
else if (min.equals("inf"))
min = dis;
else if (Integer.parseInt(min) > Integer.parseInt(dis)) {
min = dis;
}
}
} // 有新的最小值,说明还在进行优化计算,需要继续循环计算
if (!min.equals("inf")) {
if (node.getDistance().equals("inf"))
arg2.getCounter(eInf.COUNTER).increment(1L);
else {
if (Integer.parseInt(node.getDistance()) > Integer.parseInt(min))
arg2.getCounter(eInf.COUNTER).increment(1L);
}
} node.setDistance(min); arg2.write(arg0, new Text(node.toString()));
}
}
}

Node.java

 import org.apache.hadoop.util.StringUtils;

 /**
* Created by Edward on 2016/7/15.
*/
public class Node {
private String distance;
private String[] adjs; public String getDistance() {
return distance;
} public void setDistance(String distance) {
this.distance = distance;
} public String getKey(String str)
{
return str.substring(1, str.indexOf(","));
} public String getValue(String str)
{
return str.substring(str.indexOf(",")+1, str.indexOf(")"));
} public String getNodeKey(int num)
{
return getKey(adjs[num]);
} public String getNodeValue(int num)
{
return getValue(adjs[num]);
} public int getNodeNum()
{
return adjs.length;
} public void FormatNode(String str)
{
if(str.length() == 0)
return ; String[] strs = StringUtils.split(str, '\t'); adjs = new String[strs.length-1];
for(int i=0; i<strs.length; i++)
{
if(i == 0)
{
setDistance(strs[i]);
continue;
}
this.adjs[i-1]=strs[i];
}
} public String toString()
{
String str = this.distance+"" ; if(this.adjs == null)
return str; for(String s:this.adjs)
{
str = str+"\t"+s;
}
return str;
} public static void main(String[] args)
{
Node node = new Node();
node.FormatNode("1 (A,20) (B,30)");
System.out.println(node.distance+"|"+node.getNodeNum()+"|"+node.toString());
}
}

MapReduce -- 最短路径的更多相关文章

  1. Hadoop MapReduce编程 API入门系列之最短路径(十五)

    不多说,直接上代码. ======================================= Iteration: 1= Input path: out/shortestpath/input. ...

  2. mapreduce shortest way out

    相关知识 最优路径算法是无向图中满足通路上所有顶点(除起点.终点外)各异,所有边也各异的通路.应用在公路运输中,可以提供起点和终点之间的最短路径,节省运输成本.可以大大提高交通运输效率. 本实验采用D ...

  3. Mapreduce的文件和hbase共同输入

    Mapreduce的文件和hbase共同输入 package duogemap;   import java.io.IOException;   import org.apache.hadoop.co ...

  4. mapreduce多文件输出的两方法

    mapreduce多文件输出的两方法   package duogemap;   import java.io.IOException;   import org.apache.hadoop.conf ...

  5. mapreduce中一个map多个输入路径

    package duogemap; import java.io.IOException; import java.util.ArrayList; import java.util.List; imp ...

  6. Hadoop 中利用 mapreduce 读写 mysql 数据

    Hadoop 中利用 mapreduce 读写 mysql 数据   有时候我们在项目中会遇到输入结果集很大,但是输出结果很小,比如一些 pv.uv 数据,然后为了实时查询的需求,或者一些 OLAP ...

  7. [Hadoop in Action] 第5章 高阶MapReduce

    链接多个MapReduce作业 执行多个数据集的联结 生成Bloom filter   1.链接MapReduce作业   [顺序链接MapReduce作业]   mapreduce-1 | mapr ...

  8. MapReduce

    2016-12-21  16:53:49 mapred-default.xml mapreduce.input.fileinputformat.split.minsize 0 The minimum ...

  9. Johnson 全源最短路径算法

    解决单源最短路径问题(Single Source Shortest Paths Problem)的算法包括: Dijkstra 单源最短路径算法:时间复杂度为 O(E + VlogV),要求权值非负: ...

随机推荐

  1. 使用openpyxl模块将Excel中的数据导入数据库

    这里将不介绍openpyxl模块的详细操作. 主要就是记录一个使用openpyxl模块将Excel表格的数据导入数据库中的实例. from openpyxl import load_workbook ...

  2. npm、cnpm、bower安装区别

    简单地说,就是帮你下载好你需要的css或者js库,而且三者功能也都是一样的.那为什么要下载这3个不同的呢?据说npm容易被墙……而cnpm是淘宝的镜像,所以通常用cnpm代替npm.至于bower,是 ...

  3. ActiveReports 报表控件V12新特性 -- 新增JSON和CSV导出

    ActiveReports是一款专注于 .NET 平台的报表控件,全面满足 HTML5 / WinForms / ASP.NET / ASP.NET MVC / WPF 等平台下报表设计和开发工作需求 ...

  4. 商业智能BI和报表的区别?

    报表是数据展示工具,商业智能BI是数据分析工具. 报表工具是一类报表制作工具和数据展示工具,用于制作各类数据报表.图形报表.或者制作特定格式的电子发票联.流程单.收据等等. 商业智能的重点在于商业数据 ...

  5. [Android] ACTION_GET_CONTENT与ACTION_PICK的区别

    参考:AndroidSDK/docs/reference/android/content/Intent 看到相关代码,对这两个参数的区别有点搞不清. 原文地址请保留http://www.cnblogs ...

  6. 认识与入门 MarkDown 标记语言

    一.MarkDown 概念: 一种轻量级的标记语言,标记符号不超过十个,现有很多支持MarkDown语法的编辑器以及网站.Markdown从写作到完成,导出格式随心所欲,可以导出HTML,也可以导出P ...

  7. ssh中文手册

    ssh-keygen 中文手册 sshd_config 中文手册 sshd 中文手册

  8. SqlServer中sqlmaint 实用工具和xp_sqlmaint扩展过程

    sqlmaint 实用工具可以对一个或多个数据库执行一组指定的维护操作.使用 sqlmaint,可以运行 DBCC 检查.备份数据库及其事务日志.更新统计以及重建索引.所有数据库维护活动都会生成报表, ...

  9. 《SQL Server 2008从入门到精通》--20180716

    1.锁 当多个用户同时对同一个数据进行修改时会产生并发问题,使用事务就可以解决这个问题.但是为了防止其他用户修改另一个还没完成的事务中的数据,就需要在事务中用到锁. SQL Server 2008提供 ...

  10. Cisco ASA 使用ASDM 配置管理口 方法

    CISCO ASA防火墙ASDM安装和配置 准备一条串口线一边接台式机或笔记本一边接防火墙的CONSOLE 接口,通过CRT或者超级终端连接ASA在用ASDM图形管理界面之前须在串口下输入一些命令开启 ...