迪杰斯特拉算法代码以及用例

 适用于正权值的带权有向图(无向图也属于有向图)

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;
        
    }
}

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值