• 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)

    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 + "	" + 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(), '	')[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(), '	');
    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, '	');
    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+"	"+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 }
  • 相关阅读:
    Delphi映射模式实验
    restTemplate工具类
    RestTemplate中几种常见的请求方式
    RestTemplate(一)
    java.util.NoSuchElementException: No value present
    使用jsonRpc进行远程调用的时候com.googlecode.jsonrpc4j.HttpException: stream is closed
    SLF4J: Class path contains multiple SLF4J bindings.警告解决
    如何更改自己博客(博客园的)的背景
    Django中扩展Paginator实现分页
    bootstrap 导航栏
  • 原文地址:https://www.cnblogs.com/one--way/p/5673645.html
Copyright © 2020-2023  润新知