一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Java實現Dijkstra輸出最短路徑的實例

Java實現Dijkstra輸出最短路徑的實例

2021-01-09 13:52u012712087 Java教程

這篇文章主要介紹了Java實現Dijkstra輸出最短路徑的實例的相關資料,希望通過本文能幫助到大家,需要的朋友可以參考下

Java實現Dijkstra輸出指定起點到終點的最短路徑

前言:

最近在公司參加了一個比賽,其中涉及的一個問題,可以簡化成如是描述:一個二維矩陣,每個點都有權重,需要找出從指定起點到終點的最短路徑。

馬上就想到了Dijkstra算法,所以又重新溫故了一遍,這里給出Java的實現。

而輸出最短路徑的時候,在網上也進行了查閱,沒發現什么標準的方法,于是在下面的實現中,我給出了一種能夠想到的比較精簡的方式:利用prev[]數組進行遞歸輸出。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
package graph.dijsktra;
 
import graph.model.Point;
 
import java.util.*;
 
/**
 * Created by MHX on 2017/9/13.
 */
public class Dijkstra {
  private int[][] map; // 地圖結構保存
  private int[][] edges; // 鄰接矩陣
  private int[] prev; // 前驅節點標號
  private boolean[] s; // S集合中存放到起點已經算出最短路徑的點
  private int[] dist; // dist[i]表示起點到第i個節點的最短路徑
  private int pointNum; // 點的個數
  private Map<Integer, Point> indexPointMap; // 標號和點的對應關系
  private Map<Point, Integer> pointIndexMap; // 點和標號的對應關系
  private int v0; // 起點標號
  private Point startPoint; // 起點
  private Point endPoint; // 終點
  private Map<Point, Point> pointPointMap; // 保存點和權重的映射關系
  private List<Point> allPoints; // 保存所有點
  private int maxX; // x坐標的最大值
  private int maxY; // y坐標的最大值
 
  public Dijkstra(int map[][], Point startPoint, Point endPoint) {
    this.maxX = map.length;
    this.maxY = map[0].length;
    this.pointNum = maxX * maxY;
    this.map = map;
    this.startPoint = startPoint;
    this.endPoint = endPoint;
    init();
    dijkstra();
  }
 
  /**
   * 打印指定起點到終點的最短路徑
   */
  public void printShortestPath() {
    printDijkstra(pointIndexMap.get(endPoint));
  }
 
  /**
   * 初始化dijkstra
   */
  private void init() {
    // 初始化所有變量
    edges = new int[pointNum][pointNum];
    prev = new int[pointNum];
    s = new boolean[pointNum];
    dist = new int[pointNum];
    indexPointMap = new HashMap<>();
    pointIndexMap = new HashMap<>();
    pointPointMap = new HashMap<>();
    allPoints = new ArrayList<>();
 
    // 將map二維數組中的所有點轉換成自己的結構
    int count = 0;
    for (int x = 0; x < maxX; ++x) {
      for (int y = 0; y < maxY; ++y) {
        indexPointMap.put(count, new Point(x, y));
        pointIndexMap.put(new Point(x, y), count);
        count++;
        allPoints.add(new Point(x, y));
        pointPointMap.put(new Point(x, y), new Point(x, y, map[x][y]));
      }
    }
 
    // 初始化鄰接矩陣
    for (int i = 0; i < pointNum; ++i) {
      for (int j = 0; j < pointNum; ++j) {
        if (i == j) {
          edges[i][j] = 0;
        } else {
          edges[i][j] = 9999;
        }
      }
    }
 
    // 根據map上的權重初始化edges,當然這種算法是沒有單獨加起點的權重的
    for (Point point : allPoints) {
      for (Point aroundPoint : getAroundPoints(point)) {
        edges[pointIndexMap.get(point)][pointIndexMap.get(aroundPoint)] = aroundPoint.getValue();
      }
    }
 
    v0 = pointIndexMap.get(startPoint);
 
    for (int i = 0; i < pointNum; ++i) {
      dist[i] = edges[v0][i];
      if (dist[i] == 9999) {
        // 如果從0點(起點)到i點最短路徑是9999,即不可達
        // 則i節點的前驅節點不存在
        prev[i] = -1;
      } else {
        // 初始化i節點的前驅節點為起點,因為這個時候有最短路徑的都是與起點直接相連的點
        prev[i] = v0;
      }
    }
 
    dist[v0] = 0;
    s[v0] = true;
  }
 
  /**
   * dijkstra核心算法
   */
  private void dijkstra() {
    for (int i = 1; i < pointNum; ++i) { // 此時有pointNum - 1個點在U集合中,需要循環pointNum - 1次
      int minDist = 9999;
      int u = v0;
 
      for (int j = 1; j < pointNum; ++j) { // 在U集合中,找到到起點最短距離的點
        if (!s[j] && dist[j] < minDist) { // 不在S集合,就是在U集合
          u = j;
          minDist = dist[j];
        }
      }
      s[u] = true; // 將這個點放入S集合
 
      for (int j = 1; j < pointNum; ++j) { // 以當前剛從U集合放入S集合的點u為基礎,循環其可以到達的點
        if (!s[j] && edges[u][j] < 9999) {
          if (dist[u] + edges[u][j] < dist[j]) {
            dist[j] = dist[u] + edges[u][j];
            prev[j] = u;
          }
        }
      }
    }
  }
 
  private void printDijkstra(int endPointIndex) {
    if (endPointIndex == v0) {
      System.out.print(indexPointMap.get(v0) + ",");
      return;
    }
    printDijkstra(prev[endPointIndex]);
    System.out.print(indexPointMap.get(endPointIndex) + ",");
  }
 
  private List<Point> getAroundPoints(Point point) {
    List<Point> aroundPoints = new ArrayList<>();
    int x = point.getX();
    int y = point.getY();
    aroundPoints.add(pointPointMap.get(new Point(x - 1, y)));
    aroundPoints.add(pointPointMap.get(new Point(x, y + 1)));
    aroundPoints.add(pointPointMap.get(new Point(x + 1, y)));
    aroundPoints.add(pointPointMap.get(new Point(x, y - 1)));
    aroundPoints.removeAll(Collections.singleton(null)); // 剔除不在地圖范圍內的null點
    return aroundPoints;
  }
 
  public static void main(String[] args) {
    int map[][] = {
        {1, 2, 2, 2, 2, 2, 2},
        {1, 0, 2, 2, 0, 2, 2},
        {1, 2, 0, 2, 0, 2, 2},
        {1, 2, 2, 0, 2, 0, 2},
        {1, 2, 2, 2, 2, 2, 2},
        {1, 1, 1, 1, 1, 1, 1}
    }; // 每個點都代表權重,沒有方向限制
    Point startPoint = new Point(0, 3); // 起點
    Point endPoint = new Point(5, 6); // 終點
    Dijkstra dijkstra = new Dijkstra(map, startPoint, endPoint);
    dijkstra.printShortestPath();
  }
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package graph.model;
 
public class Point {
  private int x;
  private int y;
  private int value;
 
  public Point(int x, int y) {
    this.x = x;
    this.y = y;
  }
 
  public Point(int x, int y, int value) {
    this.x = x;
    this.y = y;
    this.value = value;
  }
 
  public int getX() {
    return x;
  }
 
  public void setX(int x) {
    this.x = x;
  }
 
  public int getY() {
    return y;
  }
 
  public void setY(int y) {
    this.y = y;
  }
 
  public int getValue() {
    return value;
  }
 
  public void setValue(int value) {
    this.value = value;
  }
 
  @Override
  public String toString() {
    return "{" +
        "x=" + x +
        ", y=" + y +
        '}';
  }
 
  @Override
  public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
 
    Point point = (Point) o;
 
    if (x != point.x) return false;
    return y == point.y;
  }
 
  @Override
  public int hashCode() {
    int result = x;
    result = 31 * result + y;
    return result;
  }
}

如有疑問請留言或者到本站社區交流討論,感謝閱讀,希望通過本文能幫助到大家,謝謝大家對本站的支持!

原文鏈接:http://blog.csdn.net/u012712087/article/details/77995721

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 亚洲欧美一区二区三区不卡 | 欧美一级h| 日韩精品一区二区三区毛片 | 隔壁老王国产精品福利 | 日本伊人久久 | 色倩网站 | 国产精品久久久久久久久久久威 | 亚洲精品乱码久久久久久蜜桃欧美 | 男gaygays免费网站多人 | 性一交一无一伦一精一品 | 香蕉 在线播放 | 美女鸡| 2021国产麻豆剧传媒剧情最新 | 亚洲日日做天天做日日谢 | 免费成人在线观看视频 | 欧美日韩在线观看一区二区 | 四虎影视色费永久在线观看 | 四虎影视884aa·com | 久久免费资源福利资源站 | 日本一区二区三区久久 | 免费看视频 | 农村老妇1乱69系列小说 | 婷婷sese| 日本免费观看95视频网站 | 特黄视频免费看 | 亚洲AV无码乱码在线观看浪潮 | 欧美久久天天综合香蕉伊 | 久久99re热在线播放7 | 掰开逼操 | 校花在公车上被内射好舒 | 国产中文在线视频 | 国产趴着打光屁股sp抽打 | 日韩精品免费看 | 色花堂国产精品首页第一页 | 性生大片免费看 | 男女刺激高清视频在线观看 | 国产极品麻豆91在线 | 日韩欧美精品一区二区 | 免费精品国产在线观看 | 逼里逼里香 | 欧美综合另类 |