从最短路径开始,学习Dijstar算法
下面是求最短路径问题描述:
下面是Dijkstar算法的描述:
下面是使用Dijkstar算法求解右图中的问题:
下面是图的邻接矩阵:
下面是计算过程:
下面是求解最短路径:
下面是Java代码实现,其中需要注意的问题我已经标出(一定要细心!!!!):
package greedy_algorithm;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class Dijkstra {
private Set<Integer> permanent=new HashSet<>();
private Set<Integer> temporary=new HashSet<>();
private Map<Integer, Integer> nodeMap=new HashMap<Integer, Integer>(); //key=永久节点,value=最短路径前一个节点,提高回溯效率
private int [][] m;
private Mark [][] d;
private int n;
private final static int MAX=65535;
class Mark{
private int length=MAX;
private int previous=-1;
private boolean isMarked=false;
public Mark(){}
public Mark(int length,int previous,boolean isMarked){
this.length=length;
this.previous=previous;
this.isMarked=isMarked;
}
}
public Dijkstra(){
n=6;
m=new int[][]{{ 0, 1, 4,-1,-1,-1},
{ 1, 0, 2, 7, 5,-1},
{ 4, 2, 0,-1, 1,-1},
{-1, 7,-1, 0, 3, 2},
{-1, 5, 1, 3, 0, 6},
{-1,-1,-1, 2, 6, 0}};
d=new Mark[n][n];
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
d[i][j]=new Mark();
//System.out.println(d[i][j].length+" "+d[i][j].previous+" "+d[i][j].isMarked);
}
}
}
public Dijkstra(int n,int [][]m,Mark [][]d){
this.n=n;this.m=m;this.d=d;
if(n!=m.length && n!=m[0].length &&
n!=d.length && n!=d[0].length){
System.out.println("输入格式有误");
System.exit(1);
}
}
public void shortestPath(){
ArrayList<Mark> vList;
permanent.add(0);
for(int i=1;i<n;i++){
temporary.add(i);
}
d[0][0]=new Mark(0,-1,true);
nodeMap.put(0, -1);
/*for(int q=0;q<n;q++)
System.out.print("("+d[0][q].length+","+d[0][q].previous+","+d[0][q].isMarked+") ");
System.out.println();*/
for(int i=1;i<n;i++){
for(int t:temporary){
vList=new ArrayList<Dijkstra.Mark>();
for(int p:permanent){
if(m[t][p]!=-1){
vList.add(new Mark(getLength(t, p),p,false));
}
}
if(vList.size()!=0){
d[i][t]=getMin(vList);
}
}
markNode(i);
/*for(int r=0;r<n;r++)
System.out.print("("+d[i][r].length+","+d[i][r].previous+","+d[i][r].isMarked+") ");
System.out.println();*/
}
}
public void traceBack(int end){
int node=end;
for(int i=0;i<n;i++){
if(d[i][node].isMarked==true){
System.out.println("The shortest lenth from V0 to V"+node+" is:"+d[i][node].length);
}
}
System.out.println("The shortest path is:");
trace(end,end);
}
public void trace(int end,int last){
int node =end;
if(node>=0){
trace(nodeMap.get(node),last);
if(node==last)
System.out.print("V"+node);
else
System.out.print("V"+node+"->");
}
}
public int getLength(int t,int p){
int length=m[t][p];
for(int i=0;i<n;i++){
if(d[i][p].isMarked==true){
length+=d[i][p].length;
break;
}
}
return length;
}
public Mark getMin(ArrayList<Mark> vList){
Mark mark=new Mark();
int min=MAX; //注意这里一定是min=MAX,这个地方的问题查了好久的错误!!!
//System.out.println("min="+min);
for(Mark c:vList){
//System.out.println("("+c.length+","+c.previous+","+c.isMarked+")");
if(min>c.length){
min=c.length;
mark=c;
//System.out.println("break");
}
}
//System.out.println("("+mark.length+","+mark.previous+","+mark.isMarked+")");
return mark==null?new Mark(-1,-1,false):mark;
}
public void markNode(int row){
int min=MAX;
int position=-1;
for(int j=0;j<n;j++){
if(d[row][j].length!=MAX){
if(min>d[row][j].length){
min=d[row][j].length;
position=j;
}
}
}
if(position!=-1){
d[row][position].isMarked=true;
permanent.add(position);
temporary.remove(position);
nodeMap.put(position, d[row][position].previous);
}
}
public static void main(String[] args) {
Dijkstra dijkstra=new Dijkstra();
dijkstra.shortestPath();
/*for(Map.Entry<Integer, Integer> entry:dijkstra.nodeMap.entrySet())
System.out.println(entry);*/
dijkstra.traceBack(5);
}
}