Java 迪杰斯特拉算法实现查找最短距离的实现

迪杰斯特拉算法

迪杰斯特拉算法是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法。是从一个顶点到其余各顶点的最短路径算法,解决的是有向图中最短路径问题。迪杰斯特拉算法主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。具体的计算规则我们可以通过下图进行查看。

通过这幅图我们可以简单的理解迪杰斯特拉算法算法的基础思路,下面我们就通过JAVA来实现这个算法。

算法实现

在迪杰斯特拉算法中我们需要保存从起点开始到每一个节点最短步长,这也是图中需要比较得出的步长,同时我们还需要存储该步长下的前一个节点是哪个,这样我们就可以通过终点一个一个往前推到起点,这样就出来了完整的最优路径。

每一个节点的最优前一节点

public class PreNode {
	private String preNodeName;//最优的前一个节点
	private int nodeStep;// 起点到前一个节点的步长+前一个节点本身的步长

	public PreNode(String preNodeName, int nodeStep) {
		this.preNodeName = preNodeName;
		this.nodeStep = nodeStep;
	}

	public String getPreNodeName() {
		return preNodeName;
	}

	public void setPreNodeName(String preNodeName) {
		this.preNodeName = preNodeName;
	}

	public int getNodeStep() {
		return nodeStep;
	}

	public void setNodeStep(int nodeStep) {
		this.nodeStep = nodeStep;
	}
}

定义返回的数据结构

package dijkstra;

import java.util.List;

public class MinStep {
	private boolean reachable;// 是否可达
	private int minStep;// 最短步长
	private List<String> step;// 最短路径

	public MinStep() {
	}

	public MinStep(boolean reachable, int minStep) {
		this.reachable = reachable;
		this.minStep = minStep;
	}

	public boolean isReachable() {
		return reachable;
	}

	public void setReachable(boolean reachable) {
		this.reachable = reachable;
	}

	public int getMinStep() {
		return minStep;
	}

	public void setMinStep(int minStep) {
		this.minStep = minStep;
	}

	public List<String> getStep() {
		return step;
	}

	public void setStep(List<String> step) {
		this.step = step;
	}
}

定义接口

package dijkstra;

import java.util.HashMap;

public interface Distance {
	public static final MinStep UNREACHABLE = new MinStep(false, -1);
	/**
	 * @param start
	 * @param end
	 * @param stepLength
	 * @return
	 * @Description: 起点到终点的最短路径
	 */
	public MinStep getMinStep(String start, String end, final HashMap<String, HashMap<String, Integer>> stepLength);
}

功能实现

package dijkstra;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map.Entry;

public class DistanceDijkstraImpl implements Distance {
	// 图中相邻两个节点的距离
	private HashMap<String, HashMap<String, Integer>> stepLength;
	// 非独立节点个数
	private int nodeNum;
	// 移除节点
	private HashSet<String> outNode;
	// 起点到各点的步长,key为目的节点,value为到目的节点的步长
	private HashMap<String, PreNode> nodeStep;
	// 下一次计算的节点
	private LinkedList<String> nextNode;
	// 起点、终点
	private String startNode;
	private String endNode;

	/**
	 * @param start
	 * @param end
	 * @param stepLength
	 * @return
	 * @Description: start 到 end 的最短距离
	 */
	public MinStep getMinStep(String start, String end, final HashMap<String, HashMap<String, Integer>> stepLength) {
		this.stepLength = stepLength;
		this.nodeNum = this.stepLength != null ? this.stepLength.size() : 0;
		// 起点、终点不在目标节点内,返回不可达
		if (this.stepLength == null || (!this.stepLength.containsKey(start)) || (!this.stepLength.containsKey(end))) {
			return UNREACHABLE;
		}
		initProperty(start, end);
		step();
		if (nodeStep.containsKey(end)) {
			return changeToMinStep();
		}
		return UNREACHABLE;
	}

	/**
	 * 返回最短距离以及路径
	 */
	private MinStep changeToMinStep() {
		MinStep minStep = new MinStep();
		minStep.setMinStep(nodeStep.get(endNode).getNodeStep());
		minStep.setReachable(true);
		LinkedList<String> step = new LinkedList<String>();
		minStep.setStep(step);
		// 先将终点添加到路径第一位中
		String tempNode = endNode;
		step.addFirst(tempNode);
		// 再将所经过的节点添加到路径第一位中
		while (nodeStep.containsKey(tempNode)) {
			PreNode preNode = nodeStep.get(tempNode);
			String preNodeName = preNode.getPreNodeName();
			// System.out.println(preNodeName + " " + preNode.getNodeStep());
			step.addFirst(preNodeName);
			tempNode = preNodeName;
		}
		return minStep;
	}

	/**
	 * @param start
	 * @Description: 初始化属性
	 */
	private void initProperty(String start, String end) {
		outNode = new HashSet<String>();
		nodeStep = new HashMap<String, PreNode>();
		nextNode = new LinkedList<String>();
		nextNode.add(start);
		startNode = start;
		endNode = end;
	}

	/**
	 * @param end
	 * @Description:
	 */
	private void step() {
		if (nextNode == null || nextNode.size() < 1) {
			return;
		}
		if (outNode.size() == nodeNum) {
			return;
		}
		// 获取下一个计算节点
		String start = nextNode.removeFirst();
		// 到达该节点的最小距离
		int step = 0;
		if (nodeStep.containsKey(start)) {
			step = nodeStep.get(start).getNodeStep();
		}
		// 获取该节点可达节点
		HashMap<String, Integer> nextStep = stepLength.get(start);
		Iterator<Entry<String, Integer>> iter = nextStep.entrySet().iterator();
		while (iter.hasNext()) {
			Entry<String, Integer> entry = iter.next();
			String key = entry.getKey();
			// 如果是起点到起点,不计算之间的步长
			if (key.equals(startNode)) {
				continue;
			}
			// 起点到可达节点的距离
			Integer value = entry.getValue() + step;
			if ((!nextNode.contains(key)) && (!outNode.contains(key))) {
				nextNode.add(key);
			}
			if (nodeStep.containsKey(key)) {
				// 比较步长
				if (value < nodeStep.get(key).getNodeStep()) {
					nodeStep.put(key, new PreNode(start, value));
				}
			} else {
				nodeStep.put(key, new PreNode(start, value));
			}
		}
		// 将该节点移除
		outNode.add(start);
		// 计算下一个节点
		step();
	}
}

step()逻辑解析

这一步也就是迪杰斯特拉算法的核心部分,在计算的过程中,我们需要进行如下步骤:

1)判断是否达到终止条件,如果达到终止条件,结束本次算法,如果没有达到,执行下一步;(终止条件:下一次需要计算的节点队列没有数据或已经计算过的节点数等于节点总数)

2)获取下一次计算的节点A;

3)从起点到各节点之间的最短距离map中获取到达A点的最小距离L;

4)获取A节点的可达节点B,计算从起点先到A再到B是否优于已有的其他方式到B,如果优于,则更新B节点,否则不更新;

5)判断B是否是已经移除的节点,如果不是移除的节点,把B添加到下一次需要计算的节点队列中,否则不做操作;

6)判断A节点是否还有除B以外的其他节点,如果有,执行第4)步,否则执行下一步;

7)将A节点从下一次需要计算的节点中移除添加到已经计算过的节点中;

8)执行第一步。

Demo运行

import java.util.HashMap;
import com.alibaba.fastjson.JSONObject;

public class DistanceTest {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		HashMap<String, HashMap<String, Integer>> stepLength = new HashMap<String, HashMap<String, Integer>>();
		HashMap<String, Integer> step1 = new HashMap<String, Integer>();
		stepLength.put("1", step1);
		step1.put("2", 2);

		HashMap<String, Integer> step2 = new HashMap<String, Integer>();
		stepLength.put("2", step2);
		step2.put("1", 2);
		step2.put("3", 1);

		HashMap<String, Integer> step3 = new HashMap<String, Integer>();
		stepLength.put("3", step3);
		step3.put("2", 1);
		step3.put("4", 1);
		step3.put("9", 1);

		HashMap<String, Integer> step4 = new HashMap<String, Integer>();
		stepLength.put("4", step4);
		step4.put("5", 1);
		step4.put("3", 1);

		HashMap<String, Integer> step5 = new HashMap<String, Integer>();
		stepLength.put("5", step5);
		step5.put("4", 1);

		HashMap<String, Integer> step6 = new HashMap<String, Integer>();
		stepLength.put("6", step6);
		step6.put("9", 1);

		HashMap<String, Integer> step7 = new HashMap<String, Integer>();
		stepLength.put("7", step7);
		step7.put("10", 1);

		HashMap<String, Integer> step8 = new HashMap<String, Integer>();
		stepLength.put("8", step8);
		step8.put("11", 3);

		HashMap<String, Integer> step9 = new HashMap<String, Integer>();
		stepLength.put("9", step9);
		step9.put("3", 1);
		step9.put("6", 1);
		step9.put("10", 1);

		HashMap<String, Integer> step10 = new HashMap<String, Integer>();
		stepLength.put("10", step10);
		step10.put("9", 1);
		step10.put("7", 1);
		step10.put("11", 1);

		HashMap<String, Integer> step11 = new HashMap<String, Integer>();
		stepLength.put("11", step11);
		step11.put("8", 3);
		step11.put("10", 1);

		System.out.println(JSONObject.toJSON(stepLength));

		Distance distance = new DistanceDijkstraImpl();
		MinStep step = distance.getMinStep("1", "5", stepLength);
		System.out.println(JSONObject.toJSON(step));

		step = distance.getMinStep("1", "8", stepLength);
		System.out.println(JSONObject.toJSON(step));

		step = distance.getMinStep("8", "1", stepLength);
		System.out.println(JSONObject.toJSON(step));

		step = distance.getMinStep("11", "7", stepLength);
		System.out.println(JSONObject.toJSON(step));

		step = distance.getMinStep("10", "8", stepLength);
		System.out.println(JSONObject.toJSON(step));
	}

}

{“11”:{“8”:1,“10”:1},“1”:{“2”:2},“2”:{“1”:2,“3”:1},“3”:{“4”:1,“9”:1,“2”:1},“4”:{“5”:1,“3”:1},“5”:{“4”:1},“6”:{“9”:1},“7”:{“10”:1},“8”:{“11”:1},“9”:{“6”:1,“3”:1,“10”:1},“10”:{“11”:1,“9”:1,“7”:1}}
{“minStep”:5,“step”:[“1”,“2”,“3”,“4”,“5”],“reachable”:true}
{“minStep”:7,“step”:[“1”,“2”,“3”,“9”,“10”,“11”,“8”],“reachable”:true}
{“minStep”:7,“step”:[“8”,“11”,“10”,“9”,“3”,“2”,“1”],“reachable”:true}
{“minStep”:2,“step”:[“11”,“10”,“7”],“reachable”:true}
{“minStep”:2,“step”:[“10”,“11”,“8”],“reachable”:true}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Java实现Dijkstra输出最短路径的实例

    Java实现Dijkstra输出指定起点到终点的最短路径 前言: 最近在公司参加了一个比赛,其中涉及的一个问题,可以简化成如是描述:一个二维矩阵,每个点都有权重,需要找出从指定起点到终点的最短路径. 马上就想到了Dijkstra算法,所以又重新温故了一遍,这里给出Java的实现. 而输出最短路径的时候,在网上也进行了查阅,没发现什么标准的方法,于是在下面的实现中,我给出了一种能够想到的比较精简的方式:利用prev[]数组进行递归输出. package graph.dijsktra; import

  • java实现dijkstra最短路径寻路算法

    [引用]迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径. 它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止. 基本思想 通过Dijkstra计算图G中的最短路径时,需要指定起点s(即从顶点s开始计算). 此外,引进两个集合S和U.S的作用是记录已求出最短路径的顶点(以及相应的最短路径长度),而U则是记录还未求出最短路径的顶点(以及该顶点到起点s的距离). 初始时,S中只有起点s:U中是除s之外的顶点,并且U中顶点的路径是

  • java使用Dijkstra算法实现单源最短路径

    单源最短路径问题,即在图中求出给定顶点到其它任一顶点的最短路径.在弄清楚如何求算单源最短路径问题之前,必须弄清楚最短路径的最优子结构性质. 一.最短路径的最优子结构性质 该性质描述为:如果P(i,j)={Vi....Vk..Vs...Vj}是从顶点i到j的最短路径,k和s是这条路径上的中间顶点,那么P(k,s)必定是从k到s的最短路径.下面证明该性质的正确性. 假设P(i,j)={Vi....Vk..Vs...Vj}是从顶点i到j的最短路径,则有P(i,j)=P(i,k)+P(k,s)+P(s,

  • Java实现Floyd算法求最短路径

    本文实例为大家分享了Java实现Floyd算法求最短路径的具体代码,供大家参考,具体内容如下 import java.io.FileInputStream; import java.io.FileNotFoundException; import java.util.Scanner; public class TestMainIO { /** * @param args * @throws FileNotFoundException */ public static void main(Stri

  • java实现单源最短路径

    本文采用java实现单源最短路径,并带有略微详细的注解,供大家参考,具体内容如下 package com.qf.greaph; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; /** * @author jiayoo * 7 / 30 * Dijkstra最短路径算法是一种单源最短路径 *

  • Java实现利用广度优先遍历(BFS)计算最短路径的方法

    本文实例讲述了Java实现利用广度优先遍历(BFS)计算最短路径的方法.分享给大家供大家参考.具体分析如下: 我们用字符串代表图的顶点(vertax),来模拟学校中Classroom, Square, Toilet, Canteen, South Gate, North Gate几个地点,然后计算任意两点之间的最短路径. 如下图所示: 如,我想从North Gate去Canteen, 程序的输出结果应为: BFS: From [North Gate] to [Canteen]: North Ga

  • Java Floyd算法求有权图(非负权)的最短路径并打印

    状态转移方程:d(i,j) = min(d(i,j),d(i,k)+d(k,j)),其中i<k<j 思路对于每一个k(i<k<j),全部遍历下来之后,肯定会发生一次有效的比较 public class FloydTest { private static int[][] matrix; private static int[][] path; public static void main(String[] args) { initMatrixAndPath( new int[][

  • java实现最短路径算法之Dijkstra算法

    前言 Dijkstra算法是最短路径算法中为人熟知的一种,是单起点全路径算法.该算法被称为是"贪心算法"的成功典范.本文接下来将尝试以最通俗的语言来介绍这个伟大的算法,并赋予java实现代码. 一.知识准备: 1.表示图的数据结构 用于存储图的数据结构有多种,本算法中笔者使用的是邻接矩阵. 图的邻接矩阵存储方式是用两个数组来表示图.一个一维数组存储图中顶点信息,一个二维数组(邻接矩阵)存储图中的边或弧的信息. 设图G有n个顶点,则邻接矩阵是一个n*n的方阵,定义为: 从上面可以看出,无

  • java实现Dijkstra最短路径算法

    任务描述:在一个无向图中,获取起始节点到所有其他节点的最短路径描述 Dijkstra(迪杰斯特拉)算法是典型的最短路径路由算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止. Dijkstra一般的表述通常有两种方式,一种用永久和临时标号方式,一种是用OPEN, CLOSE表方式 用OPEN,CLOSE表的方式,其采用的是贪心法的算法策略,大概过程如下: 1.声明两个集合,open和close,open用于存储未遍历的节点,close用来存储

  • Java 迪杰斯特拉算法实现查找最短距离的实现

    迪杰斯特拉算法 迪杰斯特拉算法是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法.是从一个顶点到其余各顶点的最短路径算法,解决的是有向图中最短路径问题.迪杰斯特拉算法主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.具体的计算规则我们可以通过下图进行查看. 通过这幅图我们可以简单的理解迪杰斯特拉算法算法的基础思路,下面我们就通过JAVA来实现这个算法. 算法实现 在迪杰斯特拉算法中我们需要保存从起点开始到每一个节点最短步长,这也是图中需要比较得出的步长,同时我们还

  • java图论弗洛伊德和迪杰斯特拉算法解决最短路径问题

    目录 弗洛伊德算法 算法介绍 算法图解分析   迪杰斯特拉算法 算法介绍 算法过程  弗洛伊德算法 算法介绍 算法图解分析     第一轮循环中,以A(下标为:0)作为中间顶点 [即把作为中间顶点的所有情况都进行遍历,就会得到更新距离表和前驱关系],距离表和前驱关系更新为: 弗洛伊德算法和迪杰斯特拉算法的最大区别是: 弗洛伊德算法是从各个顶点出发,求最短路径: 迪杰斯特拉算法是从某个顶点开始,求最短路径. /** * 弗洛伊德算法 * 容易理解,容易实现 */ public void floyd

  • 详解Java中Dijkstra(迪杰斯特拉)算法的图解与实现

    目录 简介 工作过程 总体思路 实现 小根堆 Dijsktra 测试 简介 Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.Dijkstra算法是很有代表性的最短路径算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹学等等.注意该算法要求图中不存在负权边.对应问题:在无向图G=(V,E)中,假设每条边E(i)的长度W(i),求由顶点V0到各节点的最短路径. 工作过

  • js图数据结构处理 迪杰斯特拉算法代码实例

    这篇文章主要介绍了js图数据结构处理 迪杰斯特拉算法代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 /*//1.确定数据结构, mapf[i][j] 为点i到点j的距离 [ Infinity 2 5 Infinity Infinity Infinity Infinity 2 6 Infinity Infinity Infinity Infinity 7 1 Infinity Infinity 2 Infinity 4 Infinity

  • Python实现迪杰斯特拉算法过程解析

    一. 迪杰斯特拉算法思想 Dijkstra算法主要针对的是有向图的单元最短路径问题,且不能出现权值为负的情况!Dijkstra算法类似于贪心算法,其应用根本在于最短路径的最优子结构性质. 最短路径的最优子结构性质: 如果P(i,j)={Vi-Vk-Vs-Vj}是从顶点i到j的最短路径,k和s是这条路径上的一个中间顶点,那么P(k,s)必定是从k到s的最短路径. 证明: 假设P(i,j)={Vi-Vk-Vs-Vj}是从顶点i到j的最短路径,则有P(i,j)=P(i,k)+P(k,s)+P(s,j)

  • C++用Dijkstra(迪杰斯特拉)算法求最短路径

    算法介绍 迪杰斯特拉算法是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法.是从一个顶点到其余各顶点的最短路径算法,解决的是有向图中最短路径问题.迪杰斯特拉算法主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.Dijkstra算法能得出最短路径的最优解,但由于它遍历计算的节点很多,所以效率低. 算法思想 按路径长度递增次序产生算法: 把顶点集合V分成两组: (1)S:已求出的顶点的集合(初始时只含有源点V0) (2)V-S=T:尚未确定的顶点集合 将T中顶点按递增

  • C++实现Dijkstra(迪杰斯特拉)算法

    Dijkstra算法 Dijkstra(迪杰斯特拉)算法是典型的最短路径路由算法,是广度优先算法的一种,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.其基本原理是:每次新扩展一个距离最短的点,更新与其相邻的点的距离.当所有边权都为正时,由于不会存在一个距离更短的没扩展过的点,所以这个点的距离永远不会再被改变,因而保证了算法的正确性.不过根据这个原理,用Dijkstra求最短路的图不能有负权边,因为扩展到负权边的时候会产生更短的距离,有可能就破

  • Python实现迪杰斯特拉算法并生成最短路径的示例代码

    def Dijkstra(network,s,d):#迪杰斯特拉算法算s-d的最短路径,并返回该路径和代价 print("Start Dijstra Path--") path=[]#s-d的最短路径 n=len(network)#邻接矩阵维度,即节点个数 fmax=999 w=[[0 for i in range(n)]for j in range(n)]#邻接矩阵转化成维度矩阵,即0→max book=[0 for i in range(n)]#是否已经是最小的标记列表 dis=[

  • 基于Python实现迪杰斯特拉和弗洛伊德算法

    图搜索之基于Python的迪杰斯特拉算法和弗洛伊德算法,供大家参考,具体内容如下 Djstela算法 #encoding=UTF-8 MAX=9 ''' Created on 2016年9月28日 @author: sx ''' b=999 G=[[0,1,5,b,b,b,b,b,b],\ [1,0,3,7,5,b,b,b,b],\ [5,3,0,b,1,7,b,b,b],\ [b,7,b,0,2,b,3,b,b],\ [b,5,1,2,0,3,6,9,b],\ [b,b,7,b,3,0,b,5

  • C/C++最短路径算法之迪杰斯特拉Dijkstra的实现详解

    目录 前言 一.迪杰斯特拉(Dijkstra)算法是什么 二.实现步骤 1.算法思路 2.进入主函数ShortestPath() 1.创建final数组并且初始化path[].dist[]数组 2.对于节点的初始化 3.进入主循环 三.全部代码(邻接表下) 四.全部代码(邻接矩阵下) 五.测试代码(邻接表下) 总结 前言 我们在生活中常常面临对路径选择的决策问题,这就要用到最短路径的算法了. 对于我这种榆木脑袋,显然迪杰斯特拉的这种算法有点高深.主要是我笨. 对于网图来说,最短路径,就是指两个顶

随机推荐