• 最短路问题之Bellman-ford算法


    题目:

      最短路:给定两个顶点,在以这两个点为起点和终点的路径中,边的权值和最小的路径。考虑权值为点之间的距离。

      单源最短路问题,Bellman-ford算法

      思路:每次循环检查所有边,可优化。

      应用于旅游等路径最小问题。

    代码:

     1 import java.util.Arrays;
     2 
     3 public class 图的最短路问题_单源 {
     4     public static void main(String[] args) {
     5         int[] shortestPath = shortestPath(0);
     6         System.out.println(Arrays.toString(shortestPath));
     7         // 输出[0, 2, 5, 7, 11, 8, 16]
     8     }
     9 
    10     /**
    11      * 求起点到各顶点的最短距离
    12      * 
    13      * @param s 起点
    14      * @return
    15      */
    16     private static int[] shortestPath(int s) {
    17         int n = graph.length;
    18         // 记录s到各顶点的最短距离
    19         int[] d = new int[n];
    20         for (int i = 0; i < n; i++) {
    21             d[i] = Integer.MAX_VALUE;
    22         }
    23         d[s] = 0;// 到自己的距离为0
    24         while (true) {
    25             boolean update = false;
    26             // 扫描所有的边
    27             for (int i = 0; i < n; i++) {
    28                 // 起点到i的最短距离还没算出来
    29                 if (d[i] == Integer.MAX_VALUE)
    30                     continue;
    31                 for (int j = 0; j < n; j++) {
    32                     int cost = graph[i][j]; // i,j之间的距离
    33                     if (cost > 0) { // i,j 两点之间有边,起点是i
    34                         if (d[j] > d[i] + cost) { // 起点先到i,i->j
    35                                                     // 两端距离加起来比起点直接到j的距离短,则更新
    36                             update = true;
    37                             d[j] = d[i] + cost;
    38                         }
    39                     }
    40                 }
    41             }
    42             // 无需任何更新,退出外循环
    43             if (!update)
    44                 break;
    45         }
    46         return d;
    47     }
    48 
    49     static int[][] graph = { 
    50             { 0, 2, 5, 0, 0, 0, 0 }, 
    51             { 2, 0, 4, 6, 10, 0, 0 }, 
    52             { 5, 4, 0, 2, 0, 0, 0 },
    53             { 0, 6, 2, 0, 0, 1, 0 }, 
    54             { 0, 10, 0, 0, 0, 3, 5 }, 
    55             { 0, 0, 0, 1, 3, 0, 9 }, 
    56             { 0, 0, 0, 0, 5, 9, 0 } 
    57             };
    58 }

       对于上一个代码。可以先把边集提取出来,这样不用每次扫描二维数组。

       Edge类:

     1 /**
     2  * 边 的封装
     3  * 边集可以用来表示图
     4  */
     5 public class Edge<T> implements Comparable<Edge>  {
     6     private T start;
     7       private T end;
     8       private int distance;
     9 
    10       public Edge(T start, T end, int distance) {
    11         this.start = start;
    12         this.end = end;
    13         this.distance = distance;
    14       }
    15 
    16       public T getStart() {
    17         return start;
    18       }
    19 
    20       public void setStart(T start) {
    21         this.start = start;
    22       }
    23 
    24       public T getEnd() {
    25         return end;
    26       }
    27 
    28       public void setEnd(T end) {
    29         this.end = end;
    30       }
    31 
    32       public int getDistance() {
    33         return distance;
    34       }
    35 
    36       public void setDistance(int distance) {
    37         this.distance = distance;
    38       }
    39 
    40       @Override
    41       public String toString() {
    42         return start + "->" + end + ":" + distance;
    43       }
    44 
    45       @Override
    46       public int compareTo(Edge obj) {
    47         int targetDis = obj.getDistance();
    48         return distance > targetDis ? 1 : (distance == targetDis ? 0 : -1);
    49       }
    50 }
    View Code

      优化过后的代码:

     1 import java.util.ArrayList;
     2 import java.util.Arrays;
     3 import java.util.List;
     4 
     5 public class 图的最短路问题_优化_边集 {
     6     public static void main(String[] args) {
     7         edges = buildEdges(graph);
     8         int[] shortestPath = shortestPath(0);
     9         System.out.println(Arrays.toString(shortestPath));
    10         // 输出[0, 2, 5, 7, 11, 8, 16]
    11     }
    12 
    13     /**
    14      * 求起点到各顶点的最短距离
    15      * 
    16      * @param s
    17      *            起点
    18      * @return
    19      */
    20     private static int[] shortestPath(int s) {
    21         int n = graph.length;
    22         // 记录s到各顶点的最短距离
    23         int[] d = new int[n];
    24         for (int i = 0; i < n; i++) {
    25             d[i] = Integer.MAX_VALUE;
    26         }
    27         d[s] = 0;// 到自己的距离为0
    28         while (true) {
    29             boolean update = false;
    30 
    31             for (Edge<Integer> e : edges) {
    32                 if (d[e.getStart()] != Integer.MAX_VALUE && d[e.getEnd()] > d[e.getStart()] + e.getDistance()) {
    33                     update = true;
    34                     d[e.getEnd()] = d[e.getStart()] + e.getDistance();
    35                 }
    36             }
    37 
    38             if (!update)
    39                 break;
    40         }
    41         return d;
    42     }
    43 
    44     static List<Edge<Integer>> edges;
    45 
    46     static List<Edge<Integer>> buildEdges(int[][] graph) {
    47         int n = graph.length;
    48         List<Edge<Integer>> edges = new ArrayList<>();
    49         for (int i = 0; i < n; i++) {
    50             for (int j = 0; j < n; j++) {
    51                 int cost = graph[i][j]; // i,j之间的距离
    52                 if (cost > 0) { // i,j 两点之间有边,起点是i
    53                     edges.add(new Edge<>(i, j, cost));
    54                 }
    55             }
    56         }
    57         return edges;
    58     }
    59 
    60     static int[][] graph = { 
    61             { 0, 2, 5, 0, 0, 0, 0 },
    62             { 2, 0, 4, 6, 10, 0, 0 }, 
    63             { 5, 4, 0, 2, 0, 0, 0 },
    64             { 0, 6, 2, 0, 0, 1, 0 }, 
    65             { 0, 10, 0, 0, 0, 3, 5 }, 
    66             { 0, 0, 0, 1, 3, 0, 9 }, 
    67             { 0, 0, 0, 0, 5, 9, 0 } 
    68             };
    69 }
    View Code
  • 相关阅读:
    ajax原理及封装
    javascript 递归调用
    CSS的五种定位方式
    vue中iframe结合window.postMessage实现父子页面间的通信
    vue将文件流的形式的图形验证码转换成图片
    路由跳转打开新窗口,传递的参数不显示在地址栏
    js判断是否是ie浏览器、360浏览器兼容模式、QQ浏览器兼容模式、搜狗浏览器兼容模式,弹出提示使用别的浏览器打开
    vue项目中使用iframe嵌入静态页面,动态获取静态页面的高度赋值给iframe的高度
    vue项目中使用iview组件中的table插件实现表头文字居中,内容文字居左
    vue前端开发实现微信支付和支付宝支付
  • 原文地址:https://www.cnblogs.com/xiaoyh/p/10415935.html
Copyright © 2020-2023  润新知