One-Way
爱一人,攀一山,追一梦

示例:

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

 

数据:

A    (B,10)    (D,5)
B    (C,1)    (D,2)
C    (E,4)
D    (B,3)    (C,9)    (E,2)
E    (A,7)    (C,6)

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,10) (D,5) B (C,1) (D,2) C (E,4) D (B,3) (C,9) (E,2) E (A,7) (C,6) 第一次mr结果: A 0 (B,10) (D,5) #从初始节点A出发,找到A到B节点和D节点的距离 B 10 (C,1) (D,2)          #找到B节点,且更新值,A到B节点目前的最短距离 C inf (E,4) D 5 (B,3) (C,9) (E,2) #找到D节点,且更新值,A到D节点目前的最短距离 E inf (A,7) (C,6) 第二次mr结果 A 0 (B,10) (D,5) B 8 (C,1) (D,2) C 11 (E,4) D 5 (B,3) (C,9) (E,2) E 7 (A,7) (C,6) 第三次mr结果 A 0 (B,10) (D,5) B 8 (C,1) (D,2) C 9 (E,4) D 5 (B,3) (C,9) (E,2) E 7 (A,7) (C,6) 第四次mr结果 A 0 (B,10) (D,5) B 8 (C,1) (D,2) C 9 (E,4) D 5 (B,3) (C,9) (E,2) E 7 (A,7) (C,6)

 

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

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

 

源代码:

RunJob.java

  1 import java.io.IOException;
  2 
  3 import org.apache.hadoop.conf.Configuration;
  4 import org.apache.hadoop.fs.FileSystem;
  5 import org.apache.hadoop.fs.Path;
  6 import org.apache.hadoop.io.Text;
  7 import org.apache.hadoop.mapreduce.Job;
  8 import org.apache.hadoop.mapreduce.Mapper;
  9 import org.apache.hadoop.mapreduce.Reducer;
 10 import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
 11 import org.apache.hadoop.mapreduce.lib.input.KeyValueTextInputFormat;
 12 import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
 13 import org.apache.hadoop.util.StringUtils;
 14 
 15 
 16 /**
 17  * Created by Edward on 2016/7/15.
 18  */
 19 public class RunJob {
 20 
 21     static enum eInf {
 22         COUNTER
 23     }
 24 
 25     public static void main(String[] args) {
 26         Configuration conf = new Configuration();
 27 
 28         conf.set("fs.defaultFS", "hdfs://node1:8020");
 29 
 30         try {
 31             FileSystem fs = FileSystem.get(conf);
 32             int i = 0;
 33             long num = 1;
 34             long tmp = 0;
 35             while (num > 0) {
 36                 i++;
 37                 conf.setInt("run.counter", i);
 38                 Job job = Job.getInstance(conf);
 39                 job.setJarByClass(RunJob.class);
 40                 job.setMapperClass(ShortestPathMapper.class);
 41                 job.setReducerClass(ShortestPathReducer.class);
 42                 job.setMapOutputKeyClass(Text.class);
 43                 job.setMapOutputValueClass(Text.class);
 44 
 45                 //key value 的格式   第一个item为key,后面的item为value
 46                 job.setInputFormatClass(KeyValueTextInputFormat.class);
 47 
 48                 if (i == 1)
 49                     FileInputFormat.addInputPath(job, new Path("/test/shortestpath/input/"));
 50                 else
 51                     FileInputFormat.addInputPath(job, new Path("/test/shortestpath/output/sp" + (i - 1)));
 52 
 53                 Path outPath = new Path("/test/shortestpath/output/sp" + i);
 54                 if (fs.exists(outPath)) {
 55                     fs.delete(outPath, true);
 56                 }
 57                 FileOutputFormat.setOutputPath(job, outPath);
 58 
 59                 boolean b = job.waitForCompletion(true);
 60 
 61                 if (b) {
 62                     num = job.getCounters().findCounter(eInf.COUNTER).getValue();
 63                     if (num == 0) {
 64                         System.out.println("执行了" + i + "次,完成最短路径的计算");
 65                     }
 66                 }
 67             }
 68 
 69         } catch (Exception e) {
 70 
 71             e.printStackTrace();
 72         }
 73 
 74     }
 75 
 76     /**
 77      * @author Edward
 78      *
 79      *         @1 A (B,10) (D,5) =>
 80      *            A 0 (B,10) (D,5)
 81      *            B 10
 82      *            D 5
 83      *         @2 B 10 (C,1) (D,2) =>
 84      *         B 10 (C,1) (D,2)
 85      *         C 11
 86      *         D 13
 87      */
 88     public static class ShortestPathMapper extends Mapper<Text, Text, Text, Text> {
 89 
 90         protected void map(Text key, Text value, Context context) throws IOException, InterruptedException {
 91             int conuter = context.getConfiguration().getInt("run.counter", 1);
 92 
 93             Node node = new Node();
 94             String distance = null;
 95             String str = null;
 96 
 97             // 第一次计算,填写默认距离 A:0 其他:inf
 98             if (conuter == 1) {
 99                 if (key.toString().equals("A") || key.toString().equals("1")) {
100                     distance = "0";
101                 } else {
102                     distance = "inf";
103                 }
104                 str = distance + "\t" + value.toString();
105             } else {
106                 str = value.toString();
107             }
108 
109             context.write(key, new Text(str));
110 
111             node.FormatNode(str);
112 
113             // 没走到此节点 退出
114             if (node.getDistance().equals("inf"))
115                 return;
116 
117             // 重新计算源点A到各点的距离
118             for (int i = 0; i < node.getNodeNum(); i++) {
119                 String k = node.getNodeKey(i);
120                 String v = new String(
121                         Integer.parseInt(node.getNodeValue(i)) + Integer.parseInt(node.getDistance()) + "");
122                 context.write(new Text(k), new Text(v));
123             }
124         }
125     }
126 
127     /**
128      * @author Edward
129      *
130      *         B 10 (C,1) (D,2)
131      *         B 8              =>
132      *         B 8 (C,1) (D,2)
133      *
134      */
135     public static class ShortestPathReducer extends Reducer<Text, Text, Text, Text> {
136 
137         protected void reduce(Text arg0, Iterable<Text> arg1, Context arg2) throws IOException, InterruptedException {
138             String min = null;
139             int i = 0;
140             String dis = "inf";
141             Node node = new Node();
142             for (Text t : arg1) {
143                 i++;
144                 dis = StringUtils.split(t.toString(), '\t')[0];
145 
146                 // 如果存在inf节点,表示存在没有计算距离的节点。
147                 // if(dis.equals("inf"))
148                 // arg2.getCounter(eInf.COUNTER).increment(1L);
149 
150                 // 判断是否存在相邻节点,如果是则需要保留信息,并找到最小距离进行更新。
151                 String[] strs = StringUtils.split(t.toString(), '\t');
152                 if (strs.length > 1) {
153                     node.FormatNode(t.toString());
154                 }
155 
156                 // 第一条数据默认是最小距离
157                 if (i == 1) {
158                     min = dis;
159                 } else {
160                     if (dis.equals("inf"))
161                         ;
162                     else if (min.equals("inf"))
163                         min = dis;
164                     else if (Integer.parseInt(min) > Integer.parseInt(dis)) {
165                         min = dis;
166                     }
167                 }
168             }
169 
170             // 有新的最小值,说明还在进行优化计算,需要继续循环计算
171             if (!min.equals("inf")) {
172                 if (node.getDistance().equals("inf"))
173                     arg2.getCounter(eInf.COUNTER).increment(1L);
174                 else {
175                     if (Integer.parseInt(node.getDistance()) > Integer.parseInt(min))
176                         arg2.getCounter(eInf.COUNTER).increment(1L);
177                 }
178             }
179 
180             node.setDistance(min);
181 
182             arg2.write(arg0, new Text(node.toString()));
183         }
184     }
185 }

 

Node.java

 1 import org.apache.hadoop.util.StringUtils;
 2 
 3 
 4 /**
 5  * Created by Edward on 2016/7/15.
 6  */
 7 public class Node {
 8     private String distance;
 9     private String[] adjs;
10 
11 
12     public String getDistance() {
13         return distance;
14     }
15 
16 
17     public void setDistance(String distance) {
18         this.distance = distance;
19     }
20 
21     public String getKey(String str)
22     {
23         return str.substring(1, str.indexOf(","));
24     }
25 
26     public String getValue(String str)
27     {
28         return str.substring(str.indexOf(",")+1, str.indexOf(")"));
29     }
30 
31     public String getNodeKey(int num)
32     {
33         return getKey(adjs[num]);
34     }
35 
36     public String getNodeValue(int num)
37     {
38         return getValue(adjs[num]);
39     }
40 
41     public int getNodeNum()
42     {
43         return adjs.length;
44     }
45 
46     public void FormatNode(String str)
47     {
48         if(str.length() == 0)
49             return ;
50 
51         String[] strs =  StringUtils.split(str, '\t');
52 
53         adjs = new String[strs.length-1];
54         for(int i=0; i<strs.length; i++)
55         {
56             if(i == 0)
57             {
58                 setDistance(strs[i]);
59                 continue;
60             }
61             this.adjs[i-1]=strs[i];
62         }
63     }
64 
65     public String toString()
66     {
67         String str = this.distance+"" ;
68 
69         if(this.adjs == null)
70             return str;
71 
72         for(String s:this.adjs)
73         {
74             str = str+"\t"+s;
75         }
76         return str;
77     }
78 
79     public static void main(String[] args)
80     {
81         Node node  = new Node();
82         node.FormatNode("1    (A,20)    (B,30)");
83         System.out.println(node.distance+"|"+node.getNodeNum()+"|"+node.toString());
84     }
85 }

 

posted on 2016-07-15 15:04  单行道|  阅读(3684)  评论(6编辑  收藏  举报