【王道408】迪杰斯特拉和弗洛伊德算法的演示

博客提及在初始化时用到特定的图,涉及Dijkstra算法,结合标签可知与算法、Java和数据结构相关,重点围绕Dijkstra算法初始化图的内容展开。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

初始化时用到的图如下
在这里插入图片描述

import java.util.Arrays;

public class Graph {
    int[][] table;int size;
    boolean[] fin;int[] distance,path;
    static final int UNACCESSIBLE = -1;
    //值设置过大会溢出
    static final int inf = Integer.MAX_VALUE/16;

    Graph(int[][] t){
        if(t.length!=t[0].length) {System.err.println("邻接表空间分配错误");return;}
        table = t;
        size = t.length;
        //将不可达替换成最大值表示,防止负权值问题影响计算
        for(int i=0;i<size;i++){
            for(int j=0;j<size;j++){
                if(table[i][j]==UNACCESSIBLE) table[i][j] = inf;
            }
        }
    }

    /**
     * 找到一个尚未确定最短路径的,离v最近的顶点
     * @return 顶点号
     */
    private int Dijkstra_nearest(){
        int min_v = inf;
        int pos = -1;
        for(int i=0;i<size;i++){
            if(!fin[i]&&distance[i]<min_v){
                min_v = distance[i];
                pos = i;
            }
        }
        if(0<=pos) fin[pos] = true;
        return pos;
    }
    /**
     * 判定是否为所有节点找到最短路径
     * @return 判断结果
     */
    private boolean Dijkstra_finish(){
        for(int i=0;i<size;i++){
            if(!fin[i]) return false;
        }
        return true;
    }

    /**
     * 构建一条更短的路径
     *  pos 中介节点
     *  v 源节点
     */
    private void Dijkstra_build_path(int pos,int v){
        for(int i=0;i<size;i++){
            //直达的距离
            int direct_dis = table[v][i];
            //通过中介到达的距离
            int proxy_dis = distance[pos] + table[pos][i];
            //对于一个尚未确定最短距离的节点(为了防止溢出现象混淆视听),如果通过中介到达目的的距离比直达短
            if(!fin[i] && proxy_dis<direct_dis){
                //将最短路径修改为通过中介到达的值
                distance[i] = proxy_dis;
                //将中介节点记录在path上
                path[i] = pos;
            }
        }
    }
    /**
     * 计算给定顶点到其他边的最短路径
     * @param v 顶点号
     * @return 最短路径数组,每一个值代表从v到当前节点的最短路径的前驱
     */
    public int[] Dijkstra(int v){
        //每个顶点的最短路径直接前驱
        path = new int[size];
        //求得的最短距离
        distance = new int[size];
        //是否找到最短路径
        fin = new boolean[size];
        //以下是初始化代码
        for(int i=0;i<size;i++){
            path[i] = v;
            distance[i] = table[v][i];
            fin[i] = false;
        }
        //找到家门口了
        path[v] = -1;
        distance[v] = 0;
        fin[v] = true;
        //下面进入循环更新信息
        while(!Dijkstra_finish()){
            //首先找到一个尚未确定最短路径的,离v最近的顶点,可以获取到这个顶点的位置
            int pos = Dijkstra_nearest();
            //接下来构建路径
            Dijkstra_build_path(pos,v);
        }
        return path;
    }

    public int[][] Floyd(){
        int[][] path = new int[size][size];
        int[][] dis_table = table.clone();
        for(int i=0;i<size;i++){
            for(int j=0;j<size;j++){
                path[i][j] = UNACCESSIBLE;
            }
        }
        //逐一选取中转节点
        for(int proxy=0;proxy<size;proxy++){
            for(int from=0;from<size;from++){
                for(int to=0;to<size;to++){
                    //目前距离表中的距离大小
                    int current_dis = dis_table[from][to];
                    //允许从新的中介节点中转后的距离大小
                    int dis_allow_new_proxy = dis_table[from][proxy] + dis_table[proxy][to];
                    //如果通过中介可以缩短距离
                    if(dis_allow_new_proxy < current_dis){
                        System.out.printf("将从%d到%d的路径由%d缩短到%d,经过节点%d\n",from,to,current_dis,dis_allow_new_proxy,proxy);
                        //记录最短距离
                        dis_table[from][to] = dis_allow_new_proxy;
                        //就将这个中介标记在路径表上
                        path[from][to] = proxy;
                    }
                    //上面的算法无法记录不需要经过中介的节点的路径,因此额外添加判断以起补充作用,如果dis_allow_new_proxy==inf,说明中介节点与源或目的节点重合
                    if(dis_allow_new_proxy!=inf && dis_allow_new_proxy==current_dis && path[from][to]==UNACCESSIBLE){
                        System.out.printf("将从%d到%d的路径由%d缩短到%d,经过节点%d\n",from,to,current_dis,dis_allow_new_proxy,proxy);
                        //就将这个中介标记在路径表上
                        path[from][to] = proxy;
                    }
                }
            }
        }
        return path;
    }

    public static void main(String[] args) {
        int[][] t = {
                {0,10,-1,-1,5},
                {-1,0,1,-1,2},
                {-1,-1,0,4,-1},
                {7,-1,6,0,-1},
                {-1,3,9,2,0}};
        Graph g = new Graph(t);
        System.out.println(Arrays.toString(g.Dijkstra(0)));
        System.out.println("-----------------------");
        for(int[] f:g.Floyd()){
            System.out.println(Arrays.toString(f));
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值