import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Dijstra {
private List<Arc> arcs;
private List<Integer> vertexs;
private List<Integer> visitedNode; //未访问点集合
private List<Integer> unVisitedNode;//已访问点集合
private Map<Integer,Double> shortestPathLength;//起始点到该点的最短距离
private Map<Integer,Integer> shortestPath;//最短距离,该点的前一个点
private final double MAXLENGTH=100000000.0d;
public Dijstra(List<Arc> arcs, List<Integer> vertexs) {
this.arcs = arcs;
this.vertexs = vertexs;
visitedNode=new ArrayList<Integer>();
unVisitedNode=new ArrayList<Integer>();
shortestPathLength=new HashMap<Integer,Double>();
shortestPath=new HashMap<Integer,Integer>();
}
public void init(int startNode){
//初始化访问与未访问集合
visitedNode.add(startNode);
for(Integer node:vertexs){
if(node.intValue()!=startNode){
unVisitedNode.add(node);
}
}
//初始化所有点到开始的最短路径
shortestPathLength.put(startNode,0.0d);
shortestPath.put(startNode, -1);
for(int unNode:unVisitedNode){
boolean access=false;
for(Arc a:arcs){
if(a.getNode1()==startNode&&a.getNode2()==unNode){ //若与起始点相连
shortestPathLength.put(unNode, a.getLength());
access=true;
break;
}
}
if(!access){
shortestPathLength.put(unNode,MAXLENGTH);
}
}
//初始化第一条路径
int lastVisitedNode=startNode;
for(int unNode:unVisitedNode){//遍历所有未访问的点
double pathLength=getLength(lastVisitedNode,unNode);//两点的距离
if(pathLength>0.0){//可达
//重新计算 路径长度,与之前的对比
double newPathLength=pathLength+shortestPathLength.get(lastVisitedNode);
double oldPathLength=shortestPathLength.get(unNode);
if(oldPathLength>=newPathLength){
shortestPath.put(unNode, lastVisitedNode);
shortestPathLength.put(unNode,newPathLength+shortestPathLength.get(lastVisitedNode));
}
}
}
}
public void execute(){
while(unVisitedNode.size()>0){
int lastVisitedNode=visitedNode.get(visitedNode.size()-1);//之前最后访问的点
for(int unNode:unVisitedNode){//遍历所有未访问的点
double pathLength=getLength(lastVisitedNode,unNode);//两点的距离
if(pathLength>0.0){//可达
//重新计算 路径长度,与之前的对比
double newPathLength=pathLength+shortestPathLength.get(lastVisitedNode);
double oldPathLength=shortestPathLength.get(unNode);
if(oldPathLength>newPathLength){
shortestPath.put(unNode, lastVisitedNode);
shortestPathLength.put(unNode,newPathLength+shortestPathLength.get(lastVisitedNode));
}
}
}
//好到所有的未访问的节点中 到起始点距离最小的点
Integer node=getMinPathLengthNode();
visitedNode.add(node);
unVisitedNode.remove(node);
}
}
public List<Integer> getShortestPath(int node){
List<Integer> path=new ArrayList<Integer>();
getPath(path,node);
Collections.reverse(path);
return path;
}
private void getPath(List<Integer> path,int node){
int pre=shortestPath.get(node);
if(pre==-1){
return;
}else{
path.add(pre);
getPath(path,pre);
}
}
//返回未访问的节点中 距离起始点最近的一个
private Integer getMinPathLengthNode(){
Integer minNode = null;
double min=10000000000.0d;
for(Integer node:unVisitedNode){
double length=shortestPathLength.get(node);
if(length<min){
minNode=node;
min=length;
}
}
return minNode;
}
private double getLength(int node1,int node2){
double length=-1.0d;
for(Arc a:arcs){
if(a.getNode1()==node1&&a.getNode2()==node2){
length=a.getLength();
}
}
return length;
}
}
class Arc{
private int node1;
private int node2;
private double length;
public Arc(int node1, int node2, double length) {
this.node1 = node1;
this.node2 = node2;
this.length = length;
}
public int getNode1() {
return node1;
}
public void setNode1(int node1) {
this.node1 = node1;
}
public int getNode2() {
return node2;
}
public void setNode2(int node2) {
this.node2 = node2;
}
public double getLength() {
return length;
}
public void setLength(double length) {
this.length = length;
}
}
List<Arc> arcs=new ArrayList<Arc>();
List<Integer> vertexs=new ArrayList<Integer>();
vertexs.add(1);
vertexs.add(2);
vertexs.add(3);
vertexs.add(4);
vertexs.add(5);
arcs.add(new Arc(1,2,10));
arcs.add(new Arc(1,4,30));
arcs.add(new Arc(1,5,100));
arcs.add(new Arc(2,3,50));
arcs.add(new Arc(3,5,10));
arcs.add(new Arc(4,3,20));
arcs.add(new Arc(4,5,60));
Dijstra dj=new Dijstra(arcs,vertexs);//Dijstra找全局最优
dj.init(1);
dj.execute();
List<Integer> result=dj.getShortestPath(5);
System.out.println(result.toString());