【数据结构与算法】迪杰斯特拉算法

news2024/12/25 8:55:05

迪杰斯特拉算法

介绍

迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径。它的主要特点是以中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止。

算法过程

设置出发顶点为 v,顶点集合 V{v1,v2,v3…vi},v 到 V 中各顶点的距离构成距离集合 Dis,Dis{d1,d2,d3…di},Dis 集合记录着 v 到图中各顶点的距离(到自身可以看做 0,v 到 vi 举例对应为 di)

  1. 从 Dis 中选择值最小的 di 并移出 Dis 集合,同时移出 V 集合中对应的顶点 vi,此时的 v 到 vi 即为最短路径
  2. 更新 Dis 集合,更新规则为:比较 v 到 V 结合中顶点的距离值,与 v 通过 vi 到 V 集合中顶点的距离值,保留值最小的一个(同时也应该更新顶点的前驱节点为 vi,表明是通过 vi 到达的)
  3. 重复执行两步骤,直到最短路径顶点为目标顶点即可结束

迪杰斯特拉算法最佳应用 - 最短路径

在这里插入图片描述

  1. 战争时期,胜利乡有 7 个村庄(A,B,C,D,E,F,G),现在有六个邮差,从 G 点出发,需要分别把邮件分别送到 A,B,C,D,E,F 六个村庄
  2. 各个村庄的距离用边线表示(权),比如 A - B 距离 5 公里
  3. 问:如何计算出 G 村庄到其他各个村庄的最短距离?
  4. 如果从其他点出发到各个点的最短距离又是多少?

代码实现

public class DijkstraAlgorithm {
    public static void main(String[] args) {
        char[] vertex = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};
        // 邻接矩阵
        int[][] matrix = new int[vertex.length][vertex.length];
        final int N = 65535; // 表示不可连接
        matrix[0] = new int[]{N, 5, 7, N, N, N, 2};
        matrix[1] = new int[]{5, N, N, 9, N, N, 3};
        matrix[2] = new int[]{7, N, N, N, 8, N, N};
        matrix[3] = new int[]{N, 9, N, N, N, 4, N};
        matrix[4] = new int[]{N, N, 8, N, N, 5, 4};
        matrix[5] = new int[]{N, N, N, 4, 5, N, 6};
        matrix[6] = new int[]{2, 3, N, N, 4, 6, N};
        // 创建图
        Graph graph = new Graph(vertex, matrix);
        graph.showGraph();
        graph.dsj(6);
        graph.showDijkstra();
    }
}

class Graph {
    private char[] vertex; // 顶点数组
    private int[][] matrix; // 邻接矩阵
    private VisitedVertex vv; // 已经访问的顶点的集合

    public Graph(char[] vertex, int[][] matrix) {
        this.vertex = vertex;
        this.matrix = matrix;
    }

    /**
     * 显示结果
     */
    public void showDijkstra() {
        vv.show();
    }

    /**
     * 显示图
     */
    public void showGraph() {
        for (int[] link : matrix) {
            System.out.println(Arrays.toString(link));
        }
    }

    /**
     * 迪杰斯特拉算法
     *
     * @param index 表示出发顶点对应的下标
     */
    public void dsj(int index) {
        vv = new VisitedVertex(vertex.length, index);
        update(index); // 更新 index 顶点到周围顶点的距离和前驱顶点
        for (int j = 1; j < vertex.length; j++) {
            index = vv.updateArr(); // 选择并返回新的访问节点
            update(index); // 更新 index 顶点到周围顶点的距离和前驱顶点
        }
    }

    /**
     * 更新 index 下标顶点到周围顶点的距离和周围定额点的前驱顶点
     *
     * @param index
     */
    private void update(int index) {
        int len = 0;
        // 根据遍历我们的邻接矩阵的 matrix[index] 行
        for (int j = 0; j < matrix[index].length; j++) {
            // len 含义是:出发顶点到 index 顶点的距离 + 从 index 顶点到 j 顶点的距离的和
            len = vv.getDis(index) + matrix[index][j];
            // 如果 j 顶点没有被访问过,并且 len 小于出发顶点到 j 顶点的距离,就需要更新
            if (!vv.in(j) && len < vv.getDis(j)) {
                vv.updatePre(j, index); // 更新 j 顶点的前驱为 index 顶点
                vv.updateDis(j, len); // 更新出发顶点到 j 顶点的距离
            }
        }
    }
}

// 已访问顶点集合
class VisitedVertex {
    // 记录各个顶点是否访问过 1 表示访问过,0 表示未访问,会动态更新
    private int[] already_arr;
    // 每个下标对应的值为前一个顶点下标,会动态更新
    private int[] pre_visited;
    // 记录出发顶点到其他所有顶点的距离,比如 G 为出发顶点,就会记录 G 到其他顶点的距离,会动态更新,求的最短距离就会存放到 dis
    private int[] dis;

    /**
     * 构造器初始化
     *
     * @param length 表示顶点的个数
     * @param index  出发顶点对应的下标
     */
    public VisitedVertex(int length, int index) {
        this.already_arr = new int[length];
        this.pre_visited = new int[length];
        this.dis = new int[length];
        // 初始化 dis
        Arrays.fill(dis, 65535);
        this.already_arr[index] = 1; // 设置出发顶点被访问过
        this.dis[index] = 0; // 设置出发顶点的访问距离为 0
    }

    /**
     * 判断 index 顶点是否被访问过
     *
     * @param index 顶点下标
     * @return 如果访问过,就返回 true,否则 返回 false
     */
    public boolean in(int index) {
        return already_arr[index] == 1;
    }

    /**
     * 更新出发顶点得到 index 顶点的距离
     *
     * @param index 顶点下标
     * @param len   长度(距离)
     */
    public void updateDis(int index, int len) {
        dis[index] = len;
    }

    /**
     * 更新 pre 顶点的前驱顶点为 index 顶点
     *
     * @param pre   要更新的顶点
     * @param index 跟新顶点
     */
    public void updatePre(int pre, int index) {
        pre_visited[pre] = index;
    }

    /**
     * 返回出发顶点到 index 顶点的距离
     *
     * @param index 顶点
     */
    public int getDis(int index) {
        return dis[index];
    }

    /**
     * 继续选择并返回新的访问顶点
     *
     * @return
     */
    public int updateArr() {
        int min = 65535, index = 0;
        for (int i = 0; i < already_arr.length; i++) {
            if (already_arr[i] == 0 && dis[i] < min) {
                min = dis[i];
                index = i;
            }
        }
        // 更新 index 顶点被访问过
        already_arr[index] = 1;
        return index;
    }

    /**
     * 显示最后的结果
     * 即将三个数组的情况输出
     */
    public void show() {

        System.out.println("=======================================");
        // 输出 already_arr
        for (int i : already_arr) {
            System.out.print(i + " ");
        }
        System.out.println();
        // 输出 pre_visited
        for (int i : pre_visited) {
            System.out.print(i + " ");
        }
        System.out.println();
        // 输出 dis
        for (int i : dis) {
            System.out.print(i + " ");
        }
        System.out.println();
        char[] vertex = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};
        int count = 0;
        for (int i : dis) {
            if (i != 65535) {
                System.out.print(vertex[count] + "(" + i + ") ");
            } else {
                System.out.println("N ");
            }
            count++;
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/909903.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

小米AI音箱联网升级折腾记录(解决配网失败+升级失败等问题)

小米AI音箱&#xff08;一代&#xff09;联网升级折腾记录 我折腾了半天终于勉强能进入下载升级包这步&#xff0c;算是成功一半吧… 总结就是&#xff0c;网络信号一定要好&#xff0c;需要不停换网找到兼容的网&#xff0c;还需要仔细配置DNS让音响连的上api.mina.mi.com 推荐…

JavaWeb-特殊文件(propertis与XML)

目录 Properties文件 一.properties介绍 二.properties使用 三.解决中文乱码问题 XML文件 一.XML介绍 二.XML文件的语法规则 三.XML的使用 Properties文件 一.properties介绍 1.什么是properties文件 Properties文件是一种常用的配置文件格式&#xff0c;用于存储键值…

linux定时备份MySQL数据库循环删除前30天的备份文件

linux定时备份MySQL数据库循环删除前30天的备份文件 一、 检查有没安装crond,如果没有&#xff0c;先安装 1、先检查一下有没有cron rpm -qa|grep cron如果输入上面命令有如下显示&#xff0c;则不需要安装 2、没有安装的话&#xff0c;就使用一下命令安装 yum -y install …

【第三阶段】kotlin语言的内置函数let

1.使用普通方法对集合的第一个元素相加 fun main() {//使用普通方法对集合的第一个元素相加var list listOf(1,2,3,4,5)var value1list.first()var resultvalue1value1println(result) }执行结果 2.使用let内置函数对集合的第一个元素相加 package Stage3fun main() {//使用…

python 打印一个条形图

背景 在python 中&#xff0c;使用 matplot 生成图表是一个很常用的方法&#xff0c;但在一些轻量级需求场合&#xff0c;例如仅做一个打印预览&#xff0c;或者快速查看&#xff0c;这些场景下调用 matplot 生成图表&#xff0c;略显繁琐。 今天介绍一个通过 DebugInfo 模块…

NC65 树表型参照 搜索全部 按钮点击事件后获取sql的方法

NC65 树表型参照 搜索全部 按钮点击事件后获取sql的方法。 /*** 返回 UIbtnLocQuery 特性值。* * return nc.ui.pub.beans.UIButton*/ /* 警告&#xff1a;此方法将重新生成。 */ private nc.ui.pub.beans.UIButton getUIbtnLocQuery() {// 搜索全部 按钮return getButtonPan…

Shell语法揭秘:深入探讨常见Linux Shell之间的语法转换

深入探讨常见Linux Shell之间的语法转换 一、引言二、Linux常用Shell&#xff1a;Bash、Zsh、Ksh、Csh、Tcsh和Fish的简介2.1、Bash、Zsh、Ksh、Csh、Tcsh和Fish的特点和用途2.2、语法差异是常见Shell之间的主要区别 三、变量和环境设置的语法差异3.1、变量定义和使用的不同语法…

【雷达】接收和去噪L波段雷达接收到的信号研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

mongodb集群

端口192.168.115.3 192.168.115.4 1192.168.115.5 下载MongoDB软件包版本为4.2.14并安装 rpm -ih --force --nodeps *.rpm 2创建文件夹mkdir -p /opt/local/mongo-cluster/conf 3.在目录里创建配置文件cd /opt/local/mongo-cluster/conf …

kubernetes--技术文档-真--集群搭建-三台服务器一主二从(非高可用)-三服务器位于同交换机中

在使用k8s之前如果不太熟悉k8s的可以先看这个文章&#xff1a; kubernetes--技术文档--基本概念--《10分钟快速了解》_一单成的博客-CSDN博客 三节点相同安装操作&#xff1a; 1、设置hosts解析 根据角色在三个服务器中运行&#xff0c;设置自己的hostname。 标识&#xf…

CG MAGIC分享如何3d Max新版本如何能在旧版本中打开呢?

三维行业来说&#xff0c;无论是三维软件还是插件&#xff0c;都是在持续更新功能的。 3d Max这款软件&#xff0c;自然也不例外&#xff0c;不断推出新版本以提供更多强大的功能和工具。 随着新版本的发布&#xff0c;旧版本用户可能面临一个问题&#xff1a; 3d Max新版本…

高速道路监控:工业路由器助力高速监控远程管理与维护

工业路由器在物联网应用中扮演着重要的角色。物联网的发展使得大量设备和传感器能够互联互通&#xff0c;而工业路由器作为连接这些设备和网络的中间桥梁&#xff0c;承担着数据传输和安全管理的重要责任。 工业路由器能够为高速监控提供网络功能&#xff0c;实现户外无线网络部…

Go语言里面的各种疑难杂症

什么是闭包&#xff1f;闭包有什么缺陷&#xff1f; func AddUpper() func(int)int{var n int 10return func (x int) int{n nxreturn n} }func main(){f : AddUpper()fmt.Println(f(1))//11fmt.Println(f(2))//13fmt.Println(f(3))//16 }&#xff08;1&#xff09; AddUpper…

Three.js 实现模型材质分解,拆分,拆解效果

原理&#xff1a;通过修改模型材质的 x,y,z 轴坐标 positon.set( x,y,z) 来实现拆解&#xff0c;分解的效果。 注意&#xff1a;支持模型材质position 修改的材质类型为 type“Mesh” ,其他类型的材质修改了position 可能没有实际效果 在上一篇 Three.js加载外部glb,fbx,gltf…

小研究 - Android 字节码动态分析分布式框架(二)

安卓平台是个多进程同时运行的系统&#xff0c;它还缺少合适的动态分析接口。因此&#xff0c;在安卓平台上进行全面的动态分析具有高难度和挑战性。已有的研究大多是针对一些安全问题的分析方法或者框架&#xff0c;无法为实现更加灵活、通用的动态分析工具的开发提供支持。此…

代码生成综述

代码生成大模型属于LLM模型的一个子类&#xff0c;理论来讲也是属于语言模型的一种特例。代码本身其实也是一种特殊的语言表示&#xff0c;所以代码模型的实现应该是具备通用自然语言和代码两部分的能力。实际的代码模型也是有两条路径来实现&#xff0c;让训练好的NLP LLM模型…

IPv4,IPv6,TCP,路由

主要回顾一下TCP&#xff0f;IP的传输过程&#xff0c;在这个过程中&#xff0c;做了什么事情 ip : 网际协议,IP协议能让世界上任意两台计算机之间进行通信。 IP协议的三大功能&#xff1a; 寻址和路由传递服务&#xff1a;不可靠&#xff08;尽最大努力交付传输数据包&…

数据仓库一分钟

数据分层 一、数据运营层&#xff1a;ODS&#xff08;Operational Data Store&#xff09; “面向主题的”数据运营层&#xff0c;也叫ODS层&#xff0c;是最接近数据源中数据的一层&#xff0c;数据源中的数据&#xff0c;经过抽取、洗净、传输&#xff0c;也就说传说中的 ETL…

模板方法模式(十六)

相信自己&#xff0c;请一定要相信自己 上一章简单介绍了代理模式(十五), 如果没有看过, 请观看上一章 一. 模板模式 引用 菜鸟教程里面的 模板模式介绍: https://www.runoob.com/design-pattern/template-pattern.html 在模板模式&#xff08;Template Pattern&#xff09;…

什么是PPS和TOD时序?授时防护设备是什么?

介绍 PPS和TOD PPS和TOD是两种用于精确时间同步的技术&#xff0c;它们在许多领域都有广泛的应用&#xff0c;总的来说&#xff0c;PPS和TOD被广泛应用于各种需要高度精确时间同步的领域&#xff0c;包括通信、测量、测试、系统集成和计算机网络等。 一、PPS PPS&#xff08…