1. 程式人生 > >Dijkstra演算法求最短路徑(java)

Dijkstra演算法求最短路徑(java)

任務描述:在一個無向圖中,獲取起始節點到所有其他節點的最短路徑描述

Dijkstra(迪傑斯特拉)演算法是典型的最短路徑路由演算法,用於計算一個節點到其他所有節點的最短路徑。主要特點是以起始點為中心向外層層擴充套件,直到擴充套件到終點為止。

Dijkstra一般的表述通常有兩種方式,一種用永久和臨時標號方式,一種是用OPEN, CLOSE表方式
用OPEN,CLOSE表的方式,其採用的是貪心法的演算法策略,大概過程如下:
1.宣告兩個集合,open和close,open用於儲存未遍歷的節點,close用來儲存已遍歷的節點
2.初始階段,將初始節點放入close,其他所有節點放入open
3.以初始節點為中心向外一層層遍歷,獲取離指定節點最近的子節點放入close並從新計算路徑,直至close包含所有子節點

程式碼例項如下:
Node物件用於封裝節點資訊,包括名字和子節點
public class Node {
	private String name;
	private Map<Node,Integer> child=new HashMap<Node,Integer>();
	public Node(String name){
		this.name=name;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Map<Node, Integer> getChild() {
		return child;
	}
	public void setChild(Map<Node, Integer> child) {
		this.child = child;
	}
}

MapBuilder用於初始化資料來源,返回圖的起始節點
public class MapBuilder {
	public Node build(Set<Node> open, Set<Node> close){
		Node nodeA=new Node("A");
		Node nodeB=new Node("B");
		Node nodeC=new Node("C");
		Node nodeD=new Node("D");
		Node nodeE=new Node("E");
		Node nodeF=new Node("F");
		Node nodeG=new Node("G");
		Node nodeH=new Node("H");
		nodeA.getChild().put(nodeB, 1);
		nodeA.getChild().put(nodeC, 1);
		nodeA.getChild().put(nodeD, 4);
		nodeA.getChild().put(nodeG, 5);
		nodeA.getChild().put(nodeF, 2);
		nodeB.getChild().put(nodeA, 1);
		nodeB.getChild().put(nodeF, 2);
		nodeB.getChild().put(nodeH, 4);
		nodeC.getChild().put(nodeA, 1);
		nodeC.getChild().put(nodeG, 3);
		nodeD.getChild().put(nodeA, 4);
		nodeD.getChild().put(nodeE, 1);
		nodeE.getChild().put(nodeD, 1);
		nodeE.getChild().put(nodeF, 1);
		nodeF.getChild().put(nodeE, 1);
		nodeF.getChild().put(nodeB, 2);
		nodeF.getChild().put(nodeA, 2);
		nodeG.getChild().put(nodeC, 3);
		nodeG.getChild().put(nodeA, 5);
		nodeG.getChild().put(nodeH, 1);
		nodeH.getChild().put(nodeB, 4);
		nodeH.getChild().put(nodeG, 1);
		open.add(nodeB);
		open.add(nodeC);
		open.add(nodeD);
		open.add(nodeE);
		open.add(nodeF);
		open.add(nodeG);
		open.add(nodeH);
		close.add(nodeA);
		return nodeA;
	}
}
圖的結構如下圖所示:


Dijkstra物件用於計算起始節點到所有其他節點的最短路徑
public class Dijkstra {
	Set<Node> open=new HashSet<Node>();
	Set<Node> close=new HashSet<Node>();
	Map<String,Integer> path=new HashMap<String,Integer>();//封裝路徑距離
	Map<String,String> pathInfo=new HashMap<String,String>();//封裝路徑資訊
	public Node init(){
		//初始路徑,因沒有A->E這條路徑,所以path(E)設定為Integer.MAX_VALUE
		path.put("B", 1);
		pathInfo.put("B", "A->B");
		path.put("C", 1);
		pathInfo.put("C", "A->C");
		path.put("D", 4);
		pathInfo.put("D", "A->D");
		path.put("E", Integer.MAX_VALUE);
		pathInfo.put("E", "A");
		path.put("F", 2);
		pathInfo.put("F", "A->F");
		path.put("G", 5);
		pathInfo.put("G", "A->G");
		path.put("H", Integer.MAX_VALUE);
		pathInfo.put("H", "A");
		//將初始節點放入close,其他節點放入open
		Node start=new MapBuilder().build(open,close);
		return start;
	}
	public void computePath(Node start){
		Node nearest=getShortestPath(start);//取距離start節點最近的子節點,放入close
		if(nearest==null){
			return;
		}
		close.add(nearest);
		open.remove(nearest);
		Map<Node,Integer> childs=nearest.getChild();
		for(Node child:childs.keySet()){
			if(open.contains(child)){//如果子節點在open中
				Integer newCompute=path.get(nearest.getName())+childs.get(child);
				if(path.get(child.getName())>newCompute){//之前設定的距離大於新計算出來的距離
					path.put(child.getName(), newCompute);
					pathInfo.put(child.getName(), pathInfo.get(nearest.getName())+"->"+child.getName());
				}
			}
		}
		computePath(start);//重複執行自己,確保所有子節點被遍歷
		computePath(nearest);//向外一層層遞迴,直至所有頂點被遍歷
	}
	public void printPathInfo(){
		Set<Map.Entry<String, String>> pathInfos=pathInfo.entrySet();
		for(Map.Entry<String, String> pathInfo:pathInfos){
			System.out.println(pathInfo.getKey()+":"+pathInfo.getValue());
		}
	}
	/**
	 * 獲取與node最近的子節點
	 */
	private Node getShortestPath(Node node){
		Node res=null;
		int minDis=Integer.MAX_VALUE;
		Map<Node,Integer> childs=node.getChild();
		for(Node child:childs.keySet()){
			if(open.contains(child)){
				int distance=childs.get(child);
				if(distance<minDis){
					minDis=distance;
					res=child;
				}
			}
		}
		return res;
	}
}

Main用於測試Dijkstra物件
public class Main {
	public static void main(String[] args) {
		Dijkstra test=new Dijkstra();
		Node start=test.init();
		test.computePath(start);
		test.printPathInfo();
	}
}

列印輸出如下:
D:A->D
E:A->F->E
F:A->F
G:A->C->G
B:A->B
C:A->C
H:A->B->H

相關推薦

Dijkstra演算法路徑(java)

任務描述:在一個無向圖中,獲取起始節點到所有其他節點的最短路徑描述 Dijkstra(迪傑斯特拉)演算法是典型的最短路徑路由演算法,用於計算一個節點到其他所有節點的最短路徑。主要特點是以起始點為中心向外層層擴充套件,直到擴充套件到終點為止。 Dijkstra一般的表述通常有

Dijkstra演算法路徑問題完整C程式碼

<pre name="code" class="cpp">/* Dijkstra演算法求圖的最短路徑問題C程式碼 */ #include <stdio.h> #include <string.h> #include <stdlib.h> #define Ma

Floyd演算法路徑——Java

前面講述了利用貪心演算法求解最短路徑的兩種演算法,分別是BFS以及Dijkstra演算法。接下來要介紹的這種是一種動態規劃的演算法——弗洛伊德演算法。 用通俗的語言來描述的話,首先我們的目標是尋找從點i到點j的最短路徑。從動態規劃的角度看問題,我們需要為這個目

dijkstra演算法路徑

希望大家能看完prim演算法後再來看這個演算法,因為兩者思路差不多。 先來看一下自定義的結構體 typedef char VexType; typedef int AdjType; typedef struct{ int n; VexTy

隨機生成圖,dijkstra演算法路徑,深度、廣度優先歷遍【待更新其他演算法

graph_node.h (鄰接連結串列節點類):#pragma once #include "pre_definition.h" //代表邊的節點 class graph_node { int serial_num; int weight;//每條邊的權值 publi

資料結構-基於鄰接矩陣實現圖的遍歷視覺化及使用Floyd、Dijkstra演算法求解路徑(JavaScript實現)

使用 JavaScript 基於鄰接矩陣實現了圖的深度、廣度遍歷,以及 Floyd、Dijkstra 演算法求解最短路徑。另外使用 SVG 實現圖的遍歷視覺化。一、輸入首先,輸入資料主要有兩個,一個是存放節點名的陣列,另一個是存放邊物件的陣列。例如://存放圖結點的陣列 va

Floyd演算法Dijkstra演算法路徑

#include <iostream> #include <cstdio> #include <vector> using namespace std; int Dis[101]; bool mark[101]; struct E { int next; i

資料結構-基於鄰接表實現圖的遍歷視覺化及使用Floyd、Dijkstra演算法求解路徑(JavaScript實現)

使用 JavaScript 基於鄰接表實現了圖的深度、廣度遍歷,以及 Floyd、Dijkstra 演算法求解最短路徑。另外使用 SVG 實現圖的遍歷視覺化。<!DOCTYPE html> <html lang="en"> <head>

迪傑斯特拉演算法路徑 C++程式碼實現

#include<iostream> #include<string> using namespace std; /*鄰接矩陣的型別定義*/ #define MAX 10000000 #define MAX_VERTEX_NUM 20 typedef

Floyd演算法路徑(附程式碼例項)

Floyd演算法 使用範圍: 1)求每對頂點的最短路徑; 2)有向圖、無向圖和混合圖; 演算法思想:       直接在圖的帶權鄰接矩陣中用插入頂點的方法依次遞推地構造出n個矩陣D(1), D(2), …, D(n), D(n)是圖的距離矩陣, 同時引入一個後繼

資料結構學習之弗洛伊德floyd演算法路徑

#include "stdio.h" #include "stdlib.h" #define MAX 20 #define INFINITY 9999 typedef bool PathMatrix[MAX+1][MAX+1][MAX+1]; typedef int Di

pku openjudge 我愛北大 floyd演算法路徑

總時間限制: 1000ms 記憶體限制: 65535kB描述 “紅樓飛雪,一時英傑……”耳邊傳來了那熟悉的歌聲。而這,只怕是我最後一次聽到這個聲音了。 想當年,我們曾經懷著豪情壯志,許下心願,走過靜園,走過一體,走過未名湖畔的每個角落。 想當年,我們也曾慷慨高歌,瞻仰民主與科學,瞻仰博雅塔頂,那百年之前的遺

貪心演算法 迪傑斯特拉演算法路徑

之前我們學習過弗洛伊德演算法求最短路徑,但是使用了三重迴圈,導致時間複雜度是O(n^3),而迪傑斯特拉演算法應該是求最短路徑的最好的演算法了。 迪傑斯特拉演算法原理 迪傑斯特拉演算法實際上是使用貪心演算法和bfs來求最短問題的,它的核心思想是,按照頂點來迭代

Dijkstra演算法路徑

基本思想 每次找到離源點最近的一個頂點,然後以該頂點為中心進行擴充套件,最終得到源點到其餘所有點的最短路徑。 基本歩驟 將所有頂點分為兩部分:已知最短路徑的頂點集合P和未知最短路徑的頂點集合Q。最開始,已知最短路徑的頂點集合P中只有源點

Java資料結構和演算法路徑---Dijkstra+Floyd

參考博文 Floyd演算法和Dijkstra演算法都不能針對帶有負權邊的圖,否則一直走負權邊,沒有最小,只有更小!! Floyd演算法 import java.util.Scanner; //Floyd演算法 class Graph{ public int[][] ad

sdut 2622 路徑(Dijkstra演算法短路)

最短路徑 Time Limit: 1000ms   Memory limit: 65536K  有疑問?點這裡^_^ 題目描述 為了準備一年一度的校賽,大家都在忙著往賽場搬運東西

C++ 路徑問題之Dijkstra演算法(一)

求最短路徑之Dijkstra演算法 Dijkstra演算法是用來求單源最短路徑問題,即給定圖G和起點s,通過演算法得到s到達其他每個頂點的最短距離。 基本思想:對圖G(V,E)設定集合S,存放已被訪問的頂點,然後每次從集合V-S中選擇與起點s的最短距離最小的一個頂點(記為u

無向圖路徑 迪傑斯特拉(dijkstra演算法實現

Dijkstra演算法說明  http://ibupu.link/?id=29namespace ConsoleApp14 { class Program { public static int M = -1; static

POJ 3255 Roadblocks (Dijkstra路徑的變形)(Dijkstra路徑

ber emp accept backtrack cau scrip 直接 hang input Roadblocks Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 16425 Ac

路徑(Bellman-Ford算法與Dijkstra算法)

dijk jks 結點 include 分組 負環 由於 blog 進行 前言 Dijkstra算法是處理單源最短路徑的有效算法,但它局限於邊的權值非負的情況,若圖中出現權值為負的邊,Dijkstra算法就會失效,求出的最短路徑就可能是錯的。這時候,就需要使用其他的算法來求