Dijkstra算法java现实

先上一张路径图

《Dijkstra算法java现实》

一共有8个点,每个点之间的连线数字,表示这两个点之间的距离,如果两个点之间无直接连线,那么只能通过其它点到达。

Dijkstra算法,网上有逼格较高的定义,描述文字不是太通俗,且不管它。

下面就以求AG的最短路径为例,谈一下具体的算法实现思路:

前提条件:定义一个close集合,分析过的点都放入此集合中,A为起点,首先放入集合。

1.以A为起点,首先寻找离A最近的相连的某个点(上图是C点)

2.找到这个C点后,循环C相连的所有点(其实B和D),重新计算A到B,A到D的临时最短距离(最初A到D不相连,AD之间距离值设为,用Integer.MAX_VALUE表示)并保存。注意此最短距离是临时的,后面路径没有完全搜索之前,可能存在更短的距离。分析过C点后,把C点放入close集合。

3.再次寻找离A最近的某个点(不在close集合中的点,即还没有分析过的点,AF=25,AB=13,AD=15,其实就是B点)

4.然后再以B点执行step2的动作,找到A距离B的所有子节点的临时最短距离,如此反复,直到close集合包括了所有点。

具体java代码如下:

/**
 * 
 */
package com.test.dijkstra;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;

/**
 * @author chaisson
 * @since 2015-5-30 上午11:51:59
 *
 */
public class Dijkstra {
	
	List<Node> openList = new ArrayList<Node>();//未访问过
	
	List<Node> closeList = new ArrayList<Node>();//已访问过
	
	Node A = new Node("A");
	Node B = new Node("B");
	Node C = new Node("C");
	Node D = new Node("D");
	Node E = new Node("E");
	Node F = new Node("F");
	Node G = new Node("G");
	Node H = new Node("H");
	
	//初始化数据节点之间的关系
	private void init(){
		
		A.linkedNode.add(B);
		A.linkedNode.add(C);
		A.linkedNode.add(F);
		A.setValue(B,14);
		A.setValue(C,4);
		A.setValue(F,25);
		
		B.linkedNode.add(A);
		B.linkedNode.add(C);
		B.linkedNode.add(E);
		B.setValue(A, 14);
		B.setValue(C, 9);
		B.setValue(E, 7);
		
		C.linkedNode.add(A);
		C.linkedNode.add(B);
		C.linkedNode.add(D);
		C.setValue(A, 4);
		C.setValue(B, 9);
		C.setValue(D, 11);
		
		D.linkedNode.add(C);
		D.linkedNode.add(E);
		D.linkedNode.add(H);
		D.setValue(C, 11);
		D.setValue(E, 12);
		D.setValue(H, 5);
		
		E.linkedNode.add(B);
		E.linkedNode.add(D);
		E.linkedNode.add(F);
		E.linkedNode.add(H);
		E.setValue(B, 7);
		E.setValue(D, 12);
		E.setValue(F, 3);
		E.setValue(H, 9);
		
		F.linkedNode.add(A);
		F.linkedNode.add(E);
		F.linkedNode.add(G);
		F.setValue(A, 25);
		F.setValue(E, 3);
		F.setValue(G, 8);
		
		G.linkedNode.add(F);
		G.linkedNode.add(H);
		G.setValue(F, 8);
		G.setValue(H, 17);
		
		H.linkedNode.add(D);
		H.linkedNode.add(E);
		H.linkedNode.add(G);
		H.setValue(D, 5);
		H.setValue(E, 9);
		H.setValue(G, 17);
		
		openList.add(A);
		openList.add(B);
		openList.add(C);
		openList.add(D);
		openList.add(E);
		openList.add(F);
		openList.add(G);
		openList.add(H);
	}
	
	//计算从start到end,走过的路径
	public void calculate(Node start,Node end){
		if(closeList.size() == openList.size()){
			System.out.println(start.getName()+"->"+end.getName()+" min.length.length:"+start.getValue(end));
			return;
		}
		Node childNode = getMinValueNode(start);//找到目前除已经分析过的节点之外的距离start节点最近的节点
		start.getAllPassNodes(childNode).add(childNode);//记录扩展到当前最近节点所有经过的节点
		if(childNode == end){
			System.out.println(start.getName()+"->"+end.getName()+" min.length:"+start.getValue(end));
			return;
		}
		//System.out.println("当前距离"+start.getName()+"最近节点为:"+childNode.getName());
		for(Node ccNode : childNode.linkedNode){
			if(closeList.contains(ccNode)){
				continue;
			}
			/**
			 * start节点到距离其最近的一个节点的其中一个子节点的距离(假设有1个或多个子节点)
			 * 即start节点到子子节点的距离
			 * 重新计算一遍A(假设start就是A,下同)到所有点的距离,与原来的距离相比较
			 */
			int ccnodeValue = start.getValue(childNode)+childNode.getValue(ccNode);//超过最大值之后,会变成负数
			if(Math.abs(ccnodeValue) < start.getValue(ccNode)){
				start.setValue(ccNode,ccnodeValue);
				System.out.println(start.getName()+"->"+ccNode.getName()+"的目前最短距离是:"+ccnodeValue);//这个最短距离只是暂时的,只要分析没有结束,最短距离可能进一步缩小	
				start.getAllPassNodes(ccNode).clear();//临时最短距离缩小,所经过路径也清除重新添加
				start.getAllPassNodes(ccNode).addAll(start.getAllPassNodes(childNode));
				start.getAllPassNodes(ccNode).add(ccNode);
			} 				
		}	
		closeList.add(childNode);
		calculate(start,end);//重复计算A到所有点的最短距离之后,再取距离A最短的节点,对其进行子节点分析【往外面节点扩展分析】
	}
	
	//取跟入参节点距离最近的节点,如果有多个相同距离的节点,则随便取其中一个
	private Node getMinValueNode(Node node){
		Node retNode = null;
		int minValue = Integer.MAX_VALUE;
		for(Node n : node.getValueMap().keySet()){
			if(closeList.contains(n)){
				continue;
			}
			if(node.getValue(n) < minValue){
				minValue = node.getValue(n);
				retNode = n;
			}
		}
		return retNode;
	}
	
	public static void main(String[] args) {
		Dijkstra d = new Dijkstra();
		d.init();
		d.closeList.add(d.A);
		d.calculate(d.A, d.G);
		//打印路径
		for(Node node : d.A.getAllPassNodes(d.G)){
			System.out.print(node.getName()+"->");
		}
	}
}


class Node {
	
	private String name;
	
	//记录本Node所有相连的Node
	public List<Node> linkedNode = new ArrayList<Node>();
	
	//记录本Node与其它Node的最短距离
	private Map<Node,Integer> valueMap = new HashMap<Node,Integer>();
	
	//记录从本Node到其它Node之间最短距离时所有经过的节点,并保持前后顺序,其实与valueMap对应
	private Map<Node,LinkedHashSet<Node>> orderSetMap = new HashMap<Node,LinkedHashSet<Node>>();
	
	public Node(String name){
		this.name = name;
	}
	
	public void setValue(Node node,Integer value){
		valueMap.put(node, value);
	}
	
	//如果没有本节点到参数节点的取值,则默认最大值
	public Integer getValue(Node node){
		return valueMap.get(node) == null? Integer.MAX_VALUE : valueMap.get(node);
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Map<Node, Integer> getValueMap() {
		return valueMap;
	}

	//取本节点到参数节点经过的所有节点集合
	public LinkedHashSet<Node> getAllPassNodes(Node node) {
		if(orderSetMap.get(node) == null){
			LinkedHashSet<Node> set = new LinkedHashSet<Node>(); 
			set.add(this);
			orderSetMap.put(node, set);
		}
		return orderSetMap.get(node);
	}
	
}

main方法执行从A到G的计算,执行结果为:

A->B的目前最短距离是:13
A->D的目前最短距离是:15
A->E的目前最短距离是:20
A->H的目前最短距离是:20
A->G的目前最短距离是:37
A->F的目前最短距离是:23
A->G的目前最短距离是:31
A->G min.length:31
A->C->B->E->F->G->

    原文作者:Dijkstra算法
    原文地址: https://blog.csdn.net/wangchsh2008/article/details/46288567
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞