适用于正权值的带权有向图(无向图也属于有向图)
package graphModel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
public class Dijstra {
public static int inf = 1000;
public static void main(String[] args) {
// 1.初始化图结构
int[][] graph = { { 0, 50, 10, inf, 70, inf }, { inf, 0, 15, inf, 10, inf }, { 20, inf, 0, 15, inf, inf },
{ inf, 20, inf, 0, 35, inf }, { inf, inf, inf, 30, 0, inf }, { inf, inf, inf, 3, inf, 0 } };
System.out.println(Arrays.toString(getShorestPath(graph,0,5)));
}
/**
* 到所有其他节点的最短路径
* @param graph
* @param sourceNode
* @return
*/
public static ArrayList<int[]> dijstra(int[][] graph, int sourceNode){
int N=graph.length;//获取顶点个数
//2.根据源节点初始化d[]和path[]并初始化集合S和U
HashSet<Integer> S = new HashSet<Integer>();//存放已经遍历过的顶点解集,其实没啥用便于理解,先保留下来
HashSet<Integer> U = new HashSet<Integer>();//存放剩余顶点集
S.add(sourceNode);
int d[] = new int[N];//存放源节点到其余节点的最短路径
int path[] = new int[N];//源节点到目的节点的最短路径上,目的节点的前一个中继节点
for(int i=0;i<N;i++) {
d[i]=graph[sourceNode][i];
if( i==sourceNode || graph[sourceNode][i]==inf)
path[i]=-1;
else
path[i]=sourceNode;
if(i!=sourceNode)
U.add(i);
}
while(!U.isEmpty()) {
//从剩余集中找到距离最小值作为中间节点
int midKey=-1;
int midValue=inf;
for(int u:U) {
if(d[u]<midValue) {
midValue=d[u];
midKey=u;
}
}
if(midKey==-1)//剩余节点均为不可达节点
break;
S.add(midKey);
U.remove(midKey);
for(int u:U) {//更新d[]和path[]
if(d[u]>d[midKey]+graph[midKey][u]) {
d[u]=d[midKey]+graph[midKey][u];
path[u]=midKey;
}
}
}
ArrayList<int[]> result = new ArrayList<int[]>();
result.add(d);
result.add(path);
return result;
}
/**
* 求出路径
* @param path
* @param sourceNode
* @param destNode
* @return
*/
public static int[] getShorestPath(int[] path,int sourceNode,int destNode) {
if(sourceNode==destNode)
return new int[] {sourceNode};
if(path[destNode]==-1)
return null;
ArrayList<Integer> tmp = new ArrayList<Integer>();
while(path[destNode]!=-1) {
tmp.add(destNode);
destNode=path[destNode];
}
tmp.add(sourceNode);
//把获得的路径倒序返回
int length = tmp.size();
int[] result = new int[length];
int j=0;
for(int i=length-1; i>=0;i--) {
result[j]=tmp.get(i);
j++;
}
return result;
}
/**
* 源节点到目的节点的最短路径
* @param graph
* @param sourceNode
* @param destNode
* @return
*/
public static int[] getShorestPath(int[][] graph,int sourceNode,int destNode) {
if(sourceNode==destNode)
return new int[] {sourceNode};
int N=graph.length;//获取顶点个数
//2.根据源节点初始化d[]和path[]并初始化集合S和U
HashSet<Integer> S = new HashSet<Integer>();//存放已经遍历过的顶点解集,其实没啥用便于理解,先保留下来
HashSet<Integer> U = new HashSet<Integer>();//存放剩余顶点集
S.add(sourceNode);
int d[] = new int[N];//存放源节点到其余节点的最短路径
int path[] = new int[N];//源节点到目的节点的最短路径上,目的节点的前一个中继节点
for(int i=0;i<N;i++) {
d[i]=graph[sourceNode][i];
if( i==sourceNode || graph[sourceNode][i]==inf)
path[i]=-1;
else
path[i]=sourceNode;
if(i!=sourceNode)
U.add(i);
}
while(!U.isEmpty()) {
//从剩余集中找到距离最小值作为中间节点
int midKey=-1;
int midValue=inf;
for(int u:U) {
if(d[u]<midValue) {
midValue=d[u];
midKey=u;
}
}
if(midKey==-1)//剩余节点均为不可达节点
break;
if(midKey==destNode)
break;
S.add(midKey);
U.remove(midKey);
for(int u:U) {//更新d[]和path[]
if(d[u]>d[midKey]+graph[midKey][u]) {
d[u]=d[midKey]+graph[midKey][u];
path[u]=midKey;
}
}
}
if(path[destNode]==-1)
return null;
ArrayList<Integer> tmp = new ArrayList<Integer>();
while(path[destNode]!=-1) {
tmp.add(destNode);
destNode=path[destNode];
}
tmp.add(sourceNode);
//把获得的路径倒序返回
int length = tmp.size();
int[] result = new int[length];
int j=0;
for(int i=length-1; i>=0;i--) {
result[j]=tmp.get(i);
j++;
}
return result;
}
}