最短路径:迪杰斯特拉算法

简介

        英文名Dijkstra

        作用:找到路中指定起点到指定终点的带权最短路径

核心步骤

        1)确定起点,终点

        2)从未走过的点中选取从起点到权值最小点作为中心点

        3)如果满足 起点到中心点权值 + 中心点到指定其他点的权值 < 起点到其他点的权值,

        即Weight[start] [center] +Weight [center] [other] < Weight [start] [center] ,

        简言之,有更短的路径就取更短的路

理论模拟

        以A为起点,D为终点,如图所示 径, 更新记录更短权值路径

 从未走过的点中选取权值最小点,即A作为中心点,标记A走过,更新起点到B、F、G的路径

 

从未走过的点中选取权值最小点,即B, 并且W:B->C + W:A->C = 12 + 10 < +oo ,更新起点A到C的路径和,

即W: A-> C =W: A-> B -> C =12+10 =22

 

 继续从未走过的点中选取权值最小点G, W: A -> E =+oo > W: A->G ->E =14+8 =22 ,

 更新W: A->E 为22

选取F, 由于W:A->F->E=16+2 =18 <22 更新 W: A-> E =18 ,

 选取E,由于W:A->E->D=18+4=22<+oo,则更新W: A->D =22

 选取C,无可更新点

 到达终点D! 最短路径为A->F->E->D ,最短路径和为22

 

Java代码实现
 顶点
//顶点类
public class Vertex {
    public String Number;  //顶点编号
    public List<Vertex>neighborVertexs;    //邻居顶点
    public Map<Vertex,Integer>weights;     //与邻居节点之间的权值

    public Vertex(String number) {
        this.Number = number;
        this.neighborVertexs=new LinkedList<>();
        this.weights=new HashMap<>();
    }
}
public class Edge {
    public Vertex start;
    public Vertex end;
    public Integer weight;

    public Edge(Vertex start, Vertex end, Integer weight) {
        this.start = start;
        this.end = end;
        this.weight = weight;
    }
}
最短路径返回结果
public class MinPathResult {
    public String minPathString;    //将最短路径拼接成字符串形式,如 A->B->C
    public List<Vertex>minPathList; //将起点到终点的路径储存在List集合中
    public Integer minPathSum;  //记录起点到终点的最短路径和
    public MinPathResult(List<Vertex> minPathList, String minPathString,Integer minPathSum) {
        this.minPathString = minPathString;
        this.minPathList = minPathList;
        this.minPathSum=minPathSum;
    }

    @Override
    public String toString() {
        return "Result{" +
                "minPathString:'" + minPathString +"  minPathSum:"+minPathSum+
                '}';
    }
}
Dijkstra算法的实现,适用于无向图
import java.util.*;
//适用于无向图
public class DijkstraOperator {
    private List<Vertex>vertexs;    //全部顶点
    private List<Edge>edges;        //所有边
    private Map<String,Vertex>vertexs_map;  //通过顶点编号找到顶点

    private final static Integer INF=Integer.MAX_VALUE;     //代表无穷大

    public DijkstraOperator(List<Vertex> vertexs, List<Edge> edges) {
        this.vertexs = vertexs;
        this.edges = edges;
        this.vertexs_map=new HashMap<>();
        //构建编号映射顶点
        for(Vertex v:vertexs)
        {
            vertexs_map.put(v.Number,v);
        }

        //填充所有顶点的邻居以及权值
        for(int i=0;i<edges.size();i++)
        {
            //填充起点的邻居,以及起点到终点的权值
            edges.get(i).start.neighborVertexs.add(edges.get(i).end);
            edges.get(i).start.weights.put(edges.get(i).end,edges.get(i).weight);

            //填充终点的邻居,以及终点到起点的权值
            edges.get(i).end.neighborVertexs.add(edges.get(i).start);
            edges.get(i).end.weights.put(edges.get(i).start,edges.get(i).weight);
        }
    }
    //获得从起点到终点之间的路径
    public MinPathResult getMinPath(String start, String end){
        //用哈希表标记某个顶点是否走过
        Map<Vertex,Boolean>visited=new HashMap<>();
        //用哈希表记录顶点的前驱
        Map<Vertex,Vertex>preVertex=new HashMap<>();
        //利用哈希表记录起点到任意一点的最短路径
        Map<Vertex,Integer>minPath=new HashMap<>();

        //初始化三个表
        for(int i=0;i<vertexs.size();i++)
        {
            //初始化每一个点都未走过
            visited.put(vertexs.get(i),false);
            //初始化每个点的前驱都是自己
            preVertex.put(vertexs.get(i),vertexs.get(i));
            //初始化起点到任意两个点之间的最短路径都是无穷大
            minPath.put(vertexs.get(i),INF);
        }

        Vertex startVertex=vertexs_map.get(start);
        Vertex endVertex=vertexs_map.get(end);

        //填充存在的路径
        for(int i=0;i<startVertex.neighborVertexs.size();i++)
        {
            //设置起点与邻居节点之间的权值
            minPath.put(startVertex.neighborVertexs.get(i),startVertex.weights.get(startVertex.neighborVertexs.get(i)));
            //设置点前驱
            preVertex.put(startVertex.neighborVertexs.get(i),startVertex);
        }
        //自己到自己的距离为0
        minPath.put(startVertex,0);

        Vertex curVertex=null;
        //一直寻路,直到找到终点
        while(curVertex!=endVertex)
        {
            Integer minWeight=Integer.MAX_VALUE;
            curVertex=null;
            //能看到的点之间选取距离最小的那个,且这个点并没有走过
            for(Vertex v:minPath.keySet())
            {
                if(!visited.get(v)&&minPath.get(v)<minWeight)
                {
                    //切换中心点
                    curVertex=v;
                    //更新最小权值
                    minWeight=minPath.get(v);
                }
            }

            //如果找不到下一个中心点,说明从起点根本到达不来终点
            if(curVertex==null)
                return null;
            //标记选取点
            visited.put(curVertex,true);

            //更新权值
            for(int i=0;i<curVertex.neighborVertexs.size();i++)
            {
                //邻居节点
                Vertex neighborVertex=curVertex.neighborVertexs.get(i);

                //计算起点到邻居节点之间新的权值
                int newWeight=minPath.get(curVertex)+curVertex.weights.get(neighborVertex);

                //找到能移动的点,如果转折之后距离更短,则记录更短的距离
                if(visited.get(neighborVertex)==false&&newWeight<minPath.get(neighborVertex))
                {
                    //记录更短距离
                    minPath.put(neighborVertex,newWeight);

                    //记录邻居节点的前驱
                    preVertex.put(neighborVertex,curVertex);
                }
            }
        }
        //起点到终点之间的最短路径
        LinkedList<Vertex>targetPath=new LinkedList<>();

        for(Vertex curVer=endVertex;curVer!=startVertex;curVer=preVertex.get(curVer))
        {
            targetPath.addFirst(curVer);
        }
        targetPath.addFirst(startVertex);

        //拼接最短路径
        StringBuffer minPathStringBuffer=new StringBuffer();
        Integer pathSum=0;
        for(int i=0;i< targetPath.size();i++)
        {
            minPathStringBuffer.append(targetPath.get(i).Number);
            if(i!= targetPath.size()-1)
            {
                pathSum=pathSum+targetPath.get(i).weights.get(targetPath.get(i+1));
                minPathStringBuffer.append("->");
            }
        }
        return new MinPathResult(targetPath, minPathStringBuffer.toString(),pathSum);
    }
}
测试函数
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner scanner=new Scanner(System.in);

        List<Vertex>vertexs=new LinkedList<>();
        List<Edge>edges=new LinkedList<>();

        System.out.println("请输入顶点的数量:");
        Integer vexcnt= scanner.nextInt();
        System.out.println("请输入这些顶点编号:");
        for(int i=0;i<vexcnt;i++)
        {
            vertexs.add(new Vertex(scanner.next()));
        }

        System.out.println("请输入边的数量:");
        Integer edgecnt= scanner.nextInt();
        System.out.println("请输入这些边的端点编号和权值:");
        for(int i=0;i<edgecnt;i++)
        {
            String number1= scanner.next();
            String number2= scanner.next();
            Integer weight= scanner.nextInt();

            Vertex v1=null;
            Vertex v2=null;
            for(int j=0;j<vertexs.size();j++)
            {
                if(vertexs.get(j).Number.equals(number1))
                    v1=vertexs.get(j);
                if(vertexs.get(j).Number.equals(number2))
                    v2=vertexs.get(j);
            }
            edges.add(new Edge(v1,v2,weight));
        }

        //定义迪杰斯特拉操作类
        DijkstraOperator dijkstra=new DijkstraOperator(vertexs,edges);

        //获取任意两点之间的最短路径结果集
        List<MinPathResult>minPathResults=new ArrayList<>();

        for(int i=0;i< vertexs.size();i++)
        {
            for(int j=i+1;j< vertexs.size();j++)
            {
                minPathResults.add(dijkstra.getMinPath(vertexs.get(i).Number,vertexs.get(j).Number));
                System.out.println(minPathResults.get(minPathResults.size()-1));
            }
        }

    }
}
测试输入与输出结果
//输入部分
请输入顶点的数量:
7
请输入这些顶点编号:
A B C D E F G
请输入边的数量:
12
请输入这些边的端点编号和权值:
A B 12
A F 16
A G 14
B C 10
B F 7
G F 9
G E 8
F C 6
F E 2
C D 3
C E 5
E D 4

//输出部分
Result{minPathString:'A->B  minPathSum:12}
Result{minPathString:'A->B->C  minPathSum:22}
Result{minPathString:'A->F->E->D  minPathSum:22}
Result{minPathString:'A->F->E  minPathSum:18}
Result{minPathString:'A->F  minPathSum:16}
Result{minPathString:'A->G  minPathSum:14}
Result{minPathString:'B->C  minPathSum:10}
Result{minPathString:'B->F->E->D  minPathSum:13}
Result{minPathString:'B->F->E  minPathSum:9}
Result{minPathString:'B->F  minPathSum:7}
Result{minPathString:'B->F->G  minPathSum:16}
Result{minPathString:'C->D  minPathSum:3}
Result{minPathString:'C->E  minPathSum:5}
Result{minPathString:'C->F  minPathSum:6}
Result{minPathString:'C->E->G  minPathSum:13}
Result{minPathString:'D->E  minPathSum:4}
Result{minPathString:'D->E->F  minPathSum:6}
Result{minPathString:'D->E->G  minPathSum:12}
Result{minPathString:'E->F  minPathSum:2}
Result{minPathString:'E->G  minPathSum:8}
Result{minPathString:'F->G  minPathSum:9}

进程已结束,退出代码为 0

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++进阶语法——智能指针【学习笔记(五)】

文章目录 1、智能指针简介1.1 原始指针&#xff08;raw pointer&#xff09;的⼀些问题1.2 智能指针&#xff08;smart pointers&#xff09; 2、智能指针&#xff08;smart pointers&#xff09;——unique_ptr2.1 unique_ptr 的声明2.2 unique_ptr 的函数2.3 ⾃定义类型使⽤ …

基于深度学习的中文情感分类 - 卷积神经网络 情感分类 情感分析 情感识别 评论情感分类 计算机竞赛

文章目录 1 前言2 情感文本分类2.1 参考论文2.2 输入层2.3 第一层卷积层&#xff1a;2.4 池化层&#xff1a;2.5 全连接softmax层&#xff1a;2.6 训练方案 3 实现3.1 sentence部分3.2 filters部分3.3 featuremaps部分3.4 1max部分3.5 concat1max部分3.6 关键代码 4 实现效果4.…

【HTML/CSS学习】margin和padding的区别

1. margin margin&#xff08;外边距&#xff09;属性定义元素周围的空间。 margin主要在元素的外部创建空白区域&#xff0c;用于分隔元素与其相邻元素之间的距离。 用处&#xff1a;可以用于调整两个元素之间的间隔。 2. padding padding&#xff08;填充&#xff09;定义…

IDE的组成

集成开发环境&#xff08;IDE&#xff0c;Integrated Development Environment &#xff09;是用于提供程序开发环境的应用程序&#xff0c;一般包括代码编辑器、编译器、调试器和图形用户界面等工具。集成了代码编写功能、分析功能、编译功能、调试功能等一体化的开发软件服务…

拿下国家级信创认证 中科驭数KPU SWIFT-2200N成为国内首款满足金融业严苛要求的DPU产品

近日&#xff0c;中科驭数KPU SWIFT-2200N低时延DPU卡&#xff0c;在中国人民银行旗下金融信创生态实验室完成测试并取得测试报告&#xff0c;这意味着中科驭数低时延网络代表性产品的应用领域从证券进一步拓展到了银行业&#xff0c;成为国内首款满足金融行业严苛要求的DPU产品…

iis前端代理后台tomcat

1)tomcat服务器配置运行好&#xff0c;服务地址位于 localhost:8080/wechat 2)iis 绑定了域名 api.abc.com 希望访问 api.abc.com/wechat时&#xff0c;实际由tomcat的服务处理; 3)iis上需要添加组件 requestRouter_amd64.msi rewrite_amd64_zh-CN.msi 4)iis进行相关配置…

记录linux运行服务提示报错/bin/java: 没有那个文件或目录

描述&#xff1a;在执行jar启动命令时候提示 没有/bin/java 这个文件或者目录&#xff1b;然后我vi /usr/bin/java&#xff0c;是存在该文件的&#xff1b;那到底是什么问题呢&#xff0c;该不是没有创建软连接吧&#xff1f; 1、执行下述命令先测试下软链接是否有创建 ln -s …

用软件模拟IPC的RTSP流,对接烟火识别算法服务,做实时的烟火检测、人员入侵检测、抽烟检测等算法

最近在研发烟火识别的算法&#xff0c;想要检验算法集成到视频分析服务之后的效果&#xff0c;发现线上的摄像机很难发现火情&#xff0c;有的很长时间都不会有检测的结果&#xff0c;于是我就需要用已经被检验过的视频文件&#xff0c;模拟一路IPC的RTSP流&#xff0c;来测试烟…

jenkins如何安装?

docker pull jenkins/jenkins:lts-centos7-jdk8 2.docker-compose.yml version: 3 services:jenkins:image: jenkins/jenkins:lts-centos7-jdk8container_name: my-jenkinsports:- "8080:8080" # 映射 Jenkins Web 界面端口volumes:- jenkins_home:/var/jenkins_h…

【MySQL数据库】初识MySQL数据库、安装MySQL

文章目录 前言一、什么是 MySQL&#xff1f;二、MySQL 的强大之处三、Ubuntu安装MySQL步骤 1: 更新包列表步骤 2: 安装 MySQL步骤 3: 启动 MySQL 服务步骤 4: 验证 MySQL 安装步骤 5: 确保 MySQL 安全性 总结 前言 在今天的数字化世界中&#xff0c;数据是企业和个人的重要资产…

matlab 中的基本绘图指令与字符串操作指令

字符串指令 创建字符串 使用单引号将字符序列括起来创建字符串使用单引号创建的字符串是一个字符数组&#xff0c;每个字符都被视为一个独立的元素 可以通过索引访问每个字符使用双引号创建的字符串是一个字符串数组&#xff0c;整个字符串被视为一个元素 无法通过索引访问单个…

【SEC 学习】美化 Linux 终端

一、步骤 1. 进入 /etc/bash.bashrc vim /etc/bash.bashrc2. 重新加载 bash.bashrc source /etc/bash.bashrc二、各参数指标 符号含义\u当前用户的账号名称\h仅取主机的第一个名字&#xff0c;如上例&#xff0c;则为fc4&#xff0c;.linux则被省略\H完整的主机名称。例如&…

一文详解防御DDoS攻击的几大有效办法

伴随互联网的飞速发展&#xff0c;网络安全问题变得越来越突出&#xff0c;其中最常见的就是DDoS攻击&#xff0c;也就是分布式拒绝服务攻击。DDoS攻击者利用计算机或其他设备的协作&#xff0c;以发送大量请求的方式导致目标超负荷&#xff0c;导致不能正常运转或“宕机”。以…

【Linux】NTP服务器配置、时间修改

查看当前系统时间date修改当前系统时间date -s "2018-2-22 19:10:30"查看硬件时间hwclock --show修改硬件时间hwclock --set --date "2018-2-22 19:10:30"同步系统时间和硬件时间hwclock --hctosys保存时钟clock –w1.设置NTP Server服务检查系统是否安装n…

医学专题--多组学在病原微生物感染中的研究思路

研究背景 病原微生物是指可以侵犯人和动物&#xff0c;引起感染甚至传染病的微生物&#xff0c;包括病毒、细菌、真菌、立克次体、寄生虫等。在我国&#xff0c;感染性疾病占所有疾病的50%以上&#xff0c;每年约1300万儿童死于感染性疾病&#xff1b;而临床上感染性疾病患者中…

BUUCTF qr 1

BUUCTF:https://buuoj.cn/challenges 题目描述&#xff1a; 这是一个二维码&#xff0c;谁用谁知道&#xff01; 密文&#xff1a; 下载附件&#xff0c;得到一张二维码图片。 解题思路&#xff1a; 1、这是一道签到题&#xff0c;扫描二维码得到flag。 flag&#xff1a;…

calloc、malloc、realloc函数的区别及用法

三者都是分配内存&#xff0c;都是stdlib.h库里的函数&#xff0c;但是也存在一些差异。 &#xff08;1&#xff09;malloc函数。其原型void *malloc(unsigned int num_bytes)&#xff1b; num_byte为要申请的空间大小&#xff0c;需要我们手动的去计算&#xff0c;如int *p …

3 tensorflow构建的模型详解

上一篇&#xff1a;2 用TensorFlow构建一个简单的神经网络-CSDN博客 1、神经网络概念 接上一篇&#xff0c;用tensorflow写了一个猜测西瓜价格的简单模型&#xff0c;理解代码前先了解下什么是神经网络。 下面是百度AI对神经网络的解释&#xff1a; 这里不赘述太多概念相关的…

linux 系统编程复习07-信号

1 复习目标 了解信号中的基本概念熟练使用信号相关的函数参考文档使用信号集操作相关函数熟练使用信号捕捉函数signal熟练使用信号捕捉函数sigaction熟练掌握使用信号完成子进程的回收 信号介绍 信号的概念 信号是信息的载体&#xff0c;Linux/UNIX 环境下&#xff0c;古老…

【计算机网络】三次握手 四次挥手

目录 1.三次握手 2.四次挥手 3.总结 三次握手和四次挥手是有连接特有的。三次握手&#xff0c;四次挥手指的是TCP有连接特点的中的步骤。建立连接(三次握手)&#xff0c;断开连接(四次挥手)。建立连接操作一般都是客户端主动发起&#xff0c;断开连接操作客户端和服务器都可…