Dijstra算法实现求解单源最短路径问题

来源:互联网 发布:大数据涉及到的技术 编辑:程序博客网 时间:2024/04/29 22:48

问题阐述:从文件中读入一个有向加权图,输入源点source,求源点到其他所有顶点的最短路径。

简单应用:比如说,你想从你居住的城市A去城市B、C、D旅游,从A到B、C、D都有很多交通路线,从这些交通路线中分别选出A到B、A到C、A到D的花钱最少的路线。

我的源程序(含测试用的代码):

//用Dijstra算法解有向加权图的单源最短路径问题,没有求出具体路径
//文件格式:如5 2 4 9999,表示这条边的起点为5,终点为2,5->2的权为4,但2没有指向5,所以2->5的权为99999(表示无穷大)
//用邻接链表来存储图,用堆栈实现优先队列

import java.io.*;
import java.util.*;

class Edge{
int adj;//邻接点
int w;//边的权
}

class Vertex{
int order;//该点输入时的顺序
int dis;//该点与源点的距离
Edge adjE[];//该点的邻边
}

class Dijkstra{
int source;//源点
int vNum;//顶点数
int eNum;//边数
int eNumV[];//记录每个顶点的出度边数
int flag[];//判断是否已经求出该点与源点的最短路径的标志
ArrayList e;//存放每一条边
Vertex v[];//顶点
Vertex top;//堆顶
ArrayList path[];//记录从源点出发到每个点的最短路径

public Dijkstra(String fileName,int source)throws IOException{
   this.source=source;
   vNum=0;
   eNum=0;
   e=new ArrayList();
  
   FileReader fr=new FileReader(fileName);
    BufferedReader bf=new BufferedReader(fr);
    String s;
    do{
       s=bf.readLine();
       if(s!=null) {e.add(s);System.out.println(s);}
        }while(s!=null);
        System.out.println(e);//
        eNum=e.size();
        int i,start=0,end=0;
       
        //第一次字符串处理,保存每一条边,以及获得顶点总数vNum
        for(i=0,vNum=0;i<eNum;i++){
        StringBuffer sb=new StringBuffer(e.get(i).toString());
        start=Integer.parseInt(sb.substring(0,sb.indexOf(" ")));
        if(start>vNum) vNum=start;
        sb.delete(0,sb.indexOf(" ")+1);
        end=Integer.parseInt(sb.substring(0,sb.indexOf(" ")));
        if(end>vNum) vNum=end;
        }//for
        System.out.println("vNum:"+vNum);//
        System.out.println("eNum:"+eNum);//
        flag=new int[vNum+1];
        path=new ArrayList[vNum+1];
        for(i=1;i<=vNum;i++){
        path[i]=new ArrayList();
        path[i].add(source);    
        if(i==source) flag[i]=1;
        else flag[i]=0;
        }
       
        //第二次字符串处理,获得每个顶点的出度边数
        eNumV=new int[vNum+1];
        for(i=1;i<eNumV.length;i++) eNumV[i]=0;
        int w1=0,w2=0;//w1表示入度,w2表示出度
        for(i=0;i<eNum;i++){
        StringBuffer sb=new StringBuffer(e.get(i).toString());
        start=Integer.parseInt(sb.substring(0,sb.indexOf(" ")));
        sb.delete(0,sb.indexOf(" ")+1);
        end=Integer.parseInt(sb.substring(0,sb.indexOf(" ")));
        sb.delete(0,sb.indexOf(" ")+1);
        w1=Integer.parseInt(sb.substring(0,sb.indexOf(" ")));
        if(w1!=99999) eNumV[start]++;
        sb.delete(0,sb.indexOf(" ")+1);
        w2=Integer.parseInt(sb.toString());
        if(w2!=99999) eNumV[end]++;
        }//for
        for(i=1;i<eNumV.length;i++) System.out.print(eNumV[i]+" ");//
       
        //第三次字符串处理,建立图的邻接链表
        v=new Vertex[vNum+1];i=1;
        for(i=1;i<vNum+1;i++){
        v[i]=new Vertex();
            v[i].adjE=new Edge[eNumV[i]+1];
            v[i].order=i;
            if(i==source) v[i].dis=100000;
            else v[i].dis=99999;
            for(int j=1;j<=eNumV[i];j++) v[i].adjE[j]=new Edge();
        }//for
        int temp[]=new int[vNum+1];//eNumV的缓存
        for(i=1;i<vNum+1;i++) temp[i]=1;
        for(i=0;i<eNum;i++){//System.out.println("i:"+i);//
        StringBuffer sb=new StringBuffer(e.get(i).toString());
        start=Integer.parseInt(sb.substring(0,sb.indexOf(" ")));       
        sb.delete(0,sb.indexOf(" ")+1);
        end=Integer.parseInt(sb.substring(0,sb.indexOf(" ")));
        v[start].adjE[temp[start]].adj=end;
        v[end].adjE[temp[end]].adj=start;//?
        sb.delete(0,sb.indexOf(" ")+1);
        w1=Integer.parseInt(sb.substring(0,sb.indexOf(" ")));
        v[start].adjE[temp[start]].w=w1;
        sb.delete(0,sb.indexOf(" ")+1);
        w2=Integer.parseInt(sb.toString());
        v[end].adjE[temp[end]].w=w2;//?
        //System.out.println("source:"+source);//
        if(start<source&&end==source) v[start].dis=w2;
        else if(start==source) v[end].dis=w1;       
        if(temp[start]<eNumV[start]) temp[start]++;
        if(temp[end]<eNumV[end]) temp[end]++;
        }//for
       
        for(i=1;i<vNum+1;i++){
        System.out.println("v"+i);
        System.out.println("v["+i+"].order:"+v[i].order);
        System.out.println("v["+i+"].dis:"+v[i].dis);
        for(int j=1;j<=eNumV[i];j++){
           System.out.println("v["+i+"].adj["+j+"].adj:"+v[i].adjE[j].adj);
           System.out.println("v["+i+"].adj["+j+"].w:"+v[i].adjE[j].w);
        }
        System.out.println();
        }//
       
}//Dijkstra

    public Vertex creatHeap(Vertex v[],int end){//难在调整后怎么知道堆顶是哪一条边
   Vertex temp=v[1];
   for(int i=end/2;i>0;i--){//换节点(即边)     
    if(2*i+1<=end&&v[2*i+1].dis<v[2*i].dis&&v[i].dis>v[2*i+1].dis){
     //System.out.println("/n"+v[i].dis+" "+v[2*i].dis+" "+v[2*i+1].dis);//
     temp=v[i];v[i]=v[2*i+1];v[2*i+1]=temp;
     //System.out.println("/n"+v[i].start+" "+v[i].end);//
    }
    else if(v[i].dis>v[2*i].dis){
     //System.out.println("/n"+v[i].dis+" "+v[2*i].dis);//
     temp=v[i];v[i]=v[2*i];v[2*i]=temp;
     //System.out.println("/n"+v[i].start+" "+v[i].end);//
    }
   }//for
   top=v[1];
   //System.out.println("top.order:"+top.order);//
   flag[v[1].order]=1;
   return top;//返回堆顶
}//creatHeap

public void update(Vertex v[],int end){
   Vertex temp;
   //System.out.println("/nv[1].order:"+v[1].order);//
   temp=v[1];v[1]=v[end];v[end]=temp;//把堆顶取出,用堆底替换
   //System.out.println("v[1].order:"+v[1].order);//
        //System.out.println("v[end].order:"+v[end].order);//
        path[v[end].order].add(v[end].order);
        for(int i=1;i<v[end].adjE.length;i++){
        int vTemp1=v[end].adjE[i].adj,vTemp2=0;
        //System.out.println("vTemp1:"+vTemp1);//
            for(int j=1;j<=end;j++){
            if(vTemp1==source) break;
            else if(v[j].order==vTemp1) {vTemp2=vTemp1;vTemp1=j;break;}
            }
            //System.out.println("vTemp1:"+vTemp1);//
        if(vTemp2!=0&&vTemp2!=source&&v[end].dis+v[end].adjE[i].w<v[vTemp1].dis){
           //System.out.println("v[vTemp1].dis:"+v[vTemp1].dis);//
           v[vTemp1].dis=v[end].dis+v[end].adjE[i].w;
           //System.out.println("v[vTemp1].dis:"+v[vTemp1].dis);//
           path[vTemp1].add(v[end].order);
        }
        }
}

}

public class DijkstraTest {

    public DijkstraTest() {
    }
   
    public static void main(String args[])throws IOException{
    Dijkstra test=new Dijkstra("DijTest2.TXT",3);
    int temp=test.vNum;
    while(temp>1){
        test.creatHeap(test.v,temp);
        test.update(test.v,temp);
        temp--;
    }
   
    for(int i=1;i<=test.vNum;i++){
       for(int j=1;j<=test.vNum;j++){
        if(test.v[j].order==i){
         System.out.println("v["+test.v[j].order+"].dis:"+test.v[j].dis);//   
         //System.out.println(test.path[test.v[j].order]);//
        }   
       }
    }
    }
   
   
}

原创粉丝点击