最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

java實現(xiàn)最短路徑算法之Dijkstra算法

 更新時間:2017年10月12日 10:31:05   作者:轉(zhuǎn)瞬之夏  
這篇文章主要介紹了java實現(xiàn)最短路徑算法之Dijkstra算法, Dijkstra算法是最短路徑算法中為人熟知的一種,是單起點全路徑算法,有興趣的可以了解一下

前言

Dijkstra算法是最短路徑算法中為人熟知的一種,是單起點全路徑算法。該算法被稱為是“貪心算法”的成功典范。本文接下來將嘗試以最通俗的語言來介紹這個偉大的算法,并賦予java實現(xiàn)代碼。

一、知識準備:

1、表示圖的數(shù)據(jù)結(jié)構(gòu)

用于存儲圖的數(shù)據(jù)結(jié)構(gòu)有多種,本算法中筆者使用的是鄰接矩陣。

圖的鄰接矩陣存儲方式是用兩個數(shù)組來表示圖。一個一維數(shù)組存儲圖中頂點信息,一個二維數(shù)組(鄰接矩陣)存儲圖中的邊或弧的信息。

設圖G有n個頂點,則鄰接矩陣是一個n*n的方陣,定義為:

從上面可以看出,無向圖的邊數(shù)組是一個對稱矩陣。所謂對稱矩陣就是n階矩陣的元滿足aij = aji。即從矩陣的左上角到右下角的主對角線為軸,右上角的元和左下角相對應的元全都是相等的。

從這個矩陣中,很容易知道圖中的信息。

(1)要判斷任意兩頂點是否有邊無邊就很容易了;

(2)要知道某個頂點的度,其實就是這個頂點vi在鄰接矩陣中第i行或(第i列)的元素之和;

(3)求頂點vi的所有鄰接點就是將矩陣中第i行元素掃描一遍,arc[i][j]為1就是鄰接點;

而有向圖講究入度和出度,頂點vi的入度為1,正好是第i列各數(shù)之和。頂點vi的出度為2,即第i行的各數(shù)之和。

有向圖的定義也類似,故不做贅述。

2、單起點全路徑

所謂單起點全路徑,就是指在一個圖中,從一個起點出發(fā),到所有節(jié)點的最短路徑。 

3、圖論的基本知識(讀者需自行尋找相關資料)

4、互補松弛條件

設標量d1,d2,....,dN滿足

dj<=di + aij,  (i,j)屬于A,

且P是以i1為起點ik為終點的路,如果

dj = di + aij, 對P的所有邊(i, j)

成立,那么P是從i1到ik的最短路。其中,滿足上面兩式的被稱為最短路問題的互補松弛條件。

二、算法思想

1、令G = (V,E)為一個帶權(quán)無向圖。G中若有兩個相鄰的節(jié)點,i和j。aij(在這及其后面都表示為下標,請注意)為節(jié)點i到節(jié)點j的權(quán)值,在本算法可以理解為距離。每個節(jié)點都有一個值di(節(jié)點標記)表示其從起點到它的某條路的距離。

2、算法初始有一個數(shù)組V用于儲存未訪問節(jié)點的列表,我們暫稱為候選列表。選定節(jié)點1為起始節(jié)點。開始時,節(jié)點1的d1=0, 其他節(jié)點di=無窮大,V為所有節(jié)點。
初始化條件后,然后開始迭代算法,直到V為空集時停止。具體迭代步驟如下:

將d值最小的節(jié)點di從候選列表中移除。(本例中V的數(shù)據(jù)結(jié)構(gòu)采用的是優(yōu)先隊列實現(xiàn)最小值出列,最好使用斐波那契對,在以前文章有過介紹,性能有大幅提示)。對于以該節(jié)點為起點的每一條邊,不包括移除V的節(jié)點, (i, j)屬于A, 若dj > di + aij(違反松弛條件),則令

dj = di + aij    , (如果j已經(jīng)從V中移除過,說明其最小距離已經(jīng)計算出,不參與此次計算)

可以看到在算法的運算工程中,節(jié)點的d值是單調(diào)不增的

具體算法圖解如下

  

三、java代碼實現(xiàn)

public class Vertex implements Comparable<Vertex>{

  /**
   * 節(jié)點名稱(A,B,C,D)
   */
  private String name;
  
  /**
   * 最短路徑長度
   */
  private int path;
  
  /**
   * 節(jié)點是否已經(jīng)出列(是否已經(jīng)處理完畢)
   */
  private boolean isMarked;
  
  public Vertex(String name){
    this.name = name;
    this.path = Integer.MAX_VALUE; //初始設置為無窮大
    this.setMarked(false);
  }
  
  public Vertex(String name, int path){
    this.name = name;
    this.path = path;
    this.setMarked(false);
  }
  
  @Override
  public int compareTo(Vertex o) {
    return o.path > path?-1:1;
  }
}

public class Graph {

  /*
   * 頂點
   */
  private List<Vertex> vertexs;

  /*
   * 邊
   */
  private int[][] edges;

  /*
   * 沒有訪問的頂點
   */
  private Queue<Vertex> unVisited;

  public Graph(List<Vertex> vertexs, int[][] edges) {
    this.vertexs = vertexs;
    this.edges = edges;
    initUnVisited();
  }
  
  /*
   * 搜索各頂點最短路徑
   */
  public void search(){
    while(!unVisited.isEmpty()){
      Vertex vertex = unVisited.element();
      //頂點已經(jīng)計算出最短路徑,設置為"已訪問"
       vertex.setMarked(true);  
      //獲取所有"未訪問"的鄰居
        List<Vertex> neighbors = getNeighbors(vertex);  
      //更新鄰居的最短路徑
      updatesDistance(vertex, neighbors);    
      pop();
    }
    System.out.println("search over");
  }
  
  /*
   * 更新所有鄰居的最短路徑
   */
  private void updatesDistance(Vertex vertex, List<Vertex> neighbors){
    for(Vertex neighbor: neighbors){
      updateDistance(vertex, neighbor);
    }
  }
  
  /*
   * 更新鄰居的最短路徑
   */
  private void updateDistance(Vertex vertex, Vertex neighbor){
    int distance = getDistance(vertex, neighbor) + vertex.getPath();
    if(distance < neighbor.getPath()){
      neighbor.setPath(distance);
    }
  }

  /*
   * 初始化未訪問頂點集合
   */
  private void initUnVisited() {
    unVisited = new PriorityQueue<Vertex>();
    for (Vertex v : vertexs) {
      unVisited.add(v);
    }
  }

  /*
   * 從未訪問頂點集合中刪除已找到最短路徑的節(jié)點
   */
  private void pop() {
    unVisited.poll();
  }

  /*
   * 獲取頂點到目標頂點的距離
   */
  private int getDistance(Vertex source, Vertex destination) {
    int sourceIndex = vertexs.indexOf(source);
    int destIndex = vertexs.indexOf(destination);
    return edges[sourceIndex][destIndex];
  }

  /*
   * 獲取頂點所有(未訪問的)鄰居
   */
  private List<Vertex> getNeighbors(Vertex v) {
    List<Vertex> neighbors = new ArrayList<Vertex>();
    int position = vertexs.indexOf(v);
    Vertex neighbor = null;
    int distance;
    for (int i = 0; i < vertexs.size(); i++) {
      if (i == position) {
        //頂點本身,跳過
        continue;
      }
      distance = edges[position][i];  //到所有頂點的距離
      if (distance < Integer.MAX_VALUE) {
        //是鄰居(有路徑可達)
        neighbor = getVertex(i);
        if (!neighbor.isMarked()) {
          //如果鄰居沒有訪問過,則加入list;
          neighbors.add(neighbor);
        }
      }
    }
    return neighbors;
  }

  /*
   * 根據(jù)頂點位置獲取頂點
   */
  private Vertex getVertex(int index) {
    return vertexs.get(index);
  }

  /*
   * 打印圖
   */
  public void printGraph() {
    int verNums = vertexs.size();
    for (int row = 0; row < verNums; row++) {
      for (int col = 0; col < verNums; col++) {
        if(Integer.MAX_VALUE == edges[row][col]){
          System.out.print("X");
          System.out.print(" ");
          continue;
        }
        System.out.print(edges[row][col]);
        System.out.print(" ");
      }
      System.out.println();
    }
  }
}

public class Test {

  public static void main(String[] args){
    List<Vertex> vertexs = new ArrayList<Vertex>();
    Vertex a = new Vertex("A", 0);
    Vertex b = new Vertex("B");
    Vertex c = new Vertex("C");
    Vertex d = new Vertex("D");
    Vertex e = new Vertex("E");
    Vertex f = new Vertex("F");
    vertexs.add(a);
    vertexs.add(b);
    vertexs.add(c);
    vertexs.add(d);
    vertexs.add(e);
    vertexs.add(f);
    int[][] edges = {
        {Integer.MAX_VALUE,6,3,Integer.MAX_VALUE,Integer.MAX_VALUE,Integer.MAX_VALUE},
        {6,Integer.MAX_VALUE,2,5,Integer.MAX_VALUE,Integer.MAX_VALUE},
        {3,2,Integer.MAX_VALUE,3,4,Integer.MAX_VALUE},
        {Integer.MAX_VALUE,5,3,Integer.MAX_VALUE,5,3},
        {Integer.MAX_VALUE,Integer.MAX_VALUE,4,5,Integer.MAX_VALUE,5},
        {Integer.MAX_VALUE,Integer.MAX_VALUE,Integer.MAX_VALUE,3,5,Integer.MAX_VALUE}
    
    };
    Graph graph = new Graph(vertexs, edges);
    graph.printGraph();
    graph.search();
  }
  
}

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

  • Java學習筆記:關于Java?double類型相加問題

    Java學習筆記:關于Java?double類型相加問題

    這篇文章主要介紹了關于Java?double類型相加問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • Spring Boot Actuator監(jiān)控器配置及使用解析

    Spring Boot Actuator監(jiān)控器配置及使用解析

    這篇文章主要介紹了Spring Boot Actuator監(jiān)控器配置及使用解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-07-07
  • 解決springboot整合cxf啟動報錯,原因是版本問題

    解決springboot整合cxf啟動報錯,原因是版本問題

    這篇文章主要介紹了解決springboot整合cxf啟動報錯,原因是版本問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • 異常點/離群點檢測算法——LOF解析

    異常點/離群點檢測算法——LOF解析

    這篇文章主要介紹了異常點/離群點檢測算法——LOF解析,通過圖解文字描述的方式詳細的解析了該算法,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • Java List集合排序?qū)崿F(xiàn)方法解析

    Java List集合排序?qū)崿F(xiàn)方法解析

    這篇文章主要介紹了Java List集合排序?qū)崿F(xiàn)方法解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-12-12
  • Springboot使用切面功能詳解

    Springboot使用切面功能詳解

    Spring?Boot?是一個基于Spring框架的項目,它簡化了基于Spring的應用開發(fā),這篇文章主要介紹了?Spring?Boot?中的切面功能,需要的可以了解下
    2025-01-01
  • JAVA調(diào)用JavaScript方法舉例詳解

    JAVA調(diào)用JavaScript方法舉例詳解

    之前在一次機緣巧合的情況下,需要時用JAVA執(zhí)行js方法,查閱了一些文檔,找到了相關解決方法,這里和大家分享一下,下面這篇文章主要給大家介紹了關于JAVA調(diào)用JavaScript方法的相關資料,需要的朋友可以參考下
    2023-10-10
  • JSON各種轉(zhuǎn)換問題(json轉(zhuǎn)List,json轉(zhuǎn)對象等)

    JSON各種轉(zhuǎn)換問題(json轉(zhuǎn)List,json轉(zhuǎn)對象等)

    這篇文章主要介紹了JSON各種轉(zhuǎn)換問題(json轉(zhuǎn)List,json轉(zhuǎn)對象等),本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-03-03
  • SpringBoot集成QQ第三方登陸的實現(xiàn)

    SpringBoot集成QQ第三方登陸的實現(xiàn)

    這篇文章主要介紹了SpringBoot集成QQ第三方登陸的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-11-11
  • SpringBoot+SpringSecurity實現(xiàn)認證的流程詳解

    SpringBoot+SpringSecurity實現(xiàn)認證的流程詳解

    這篇文章主要介紹了SpringBoot+SpringSecurity實現(xiàn)認證的流程,文中通過代碼示例和圖文結(jié)合的方式講解的非常詳細,對大家的學習或工作有一定的幫助,需要的朋友可以參考下
    2024-05-05

最新評論

梓潼县| 万载县| 兰溪市| 永济市| 托里县| 静海县| 建宁县| 江门市| 安岳县| 彭水| 岫岩| 广元市| 烟台市| 城口县| 白银市| 贵溪市| 日照市| 延川县| 高台县| 留坝县| 垦利县| 江北区| 剑阁县| 龙川县| 行唐县| 临泽县| 防城港市| 名山县| 卢龙县| 图木舒克市| 榆社县| 葵青区| 武清区| 北流市| 沁阳市| 辽宁省| 乐亭县| 武山县| 慈溪市| 张家口市| 康乐县|