图的单源最短路径问题

目录

一、简述

二、前置配置

三、迪杰斯特拉算法

四、改进的迪杰斯特拉算法

五、贝尔曼福特算法


一、简述

        图是一种比较常用的数据结构,将问题转换成图相关的思路也是比较常用的。

        图的单源最短路径问题,也就是图中某一个节点到图中其他节点的最短路径大小,常用的算法就是迪杰斯特拉算法和贝尔曼福特算法,两者是从不同的角度来对这个问题进行分析的,但是迪杰斯特拉算法并不适用于有负权重的情况,而贝尔曼福特算法则是应用范围更广泛,能解决带有负权重问题的场景。

二、前置配置

        边类:

package graph;

/**
 * 边类
 */
public class Edge {
    Vertex vertex;
    int weight;

    public Edge() {
    }

    public Edge(Vertex vertex) {
        this.vertex = vertex;
    }

    public Edge(Vertex vertex, int weight) {
        this.vertex = vertex;
        this.weight = weight;
    }

    public Vertex getVertex() {
        return vertex;
    }

    public void setVertex(Vertex vertex) {
        this.vertex = vertex;
    }

    public int getWeight() {
        return weight;
    }

    public void setWeight(int weight) {
        this.weight = weight;
    }
}

        结点类:

package graph;

import java.util.List;

/**
 * 顶点类
 */
public class Vertex {
    String name;
    List<Edge> edges;
    boolean flag;//是否被访问过
    int inDegree;//结点的入度

    int status;//状态, 0-未访问过, 1-正在访问,用于检测环,2-已经访问过

    int dist=Integer.MAX_VALUE;//距离

    Vertex pre=null;

    public Vertex() {
    }

    public Vertex(String name, List<Edge> edges) {
        this.name = name;
        this.edges = edges;
    }

    public Vertex(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<Edge> getEdges() {
        return edges;
    }

    public void setEdges(List<Edge> edges) {
        this.edges = edges;
    }
}

三、迪杰斯特拉算法

        迪杰斯特拉算法是从节点出发来完成单源最短路径问题的,我们可以将整个图分为两个区域,一个区域就是已经找到从源点到该点的最短路径,另一个区域则是未找到的。

        从已经找到的区域到未找到的区域的所有相连节点的边,从中取最小值,并将该边所对应的未找到区域的结点加入到已经找到找到的区域,并更改其最短路径。

        最后,通过将所有联通的结点的最短路径找到,即可结束。

        代码:

package graph;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class Dijkstra {
    public static void main(String[] args) {
        Vertex v1=new Vertex("v1",new LinkedList<>());
        Vertex v2=new Vertex("v2",new LinkedList<>());
        Vertex v3=new Vertex("v3",new LinkedList<>());
        Vertex v4=new Vertex("v4",new LinkedList<>());
        Vertex v5=new Vertex("v5",new LinkedList<>());
        Vertex v6=new Vertex("v6",new LinkedList<>());

        v1.edges.add(new Edge(v3,9));
        v1.edges.add(new Edge(v2,7));
        v1.edges.add(new Edge(v6,14));

        v2.edges.add(new Edge(v4,15));

        v3.edges.add(new Edge(v4,11));
        v3.edges.add(new Edge(v6,2));

        v4.edges.add(new Edge(v5,6));

        v6.edges.add(new Edge(v5,9));

        List<Vertex> graph=new ArrayList<>();
        graph.add(v1);
        graph.add(v2);
        graph.add(v3);
        graph.add(v4);
        graph.add(v5);
        graph.add(v6);

        dijkstra(graph,v1);
    }

    private static void dijkstra(List<Vertex> graph,Vertex vertex) {
        ArrayList<Vertex> list=new ArrayList<>(graph);
        vertex.dist=0;
        while(!list.isEmpty()){
            //选取当前顶点(距离最小的顶点)
            Vertex curr=chooseMinDistVertex(list);
            //更新当前顶点邻居距离
            updateNeighboursDist(curr,list);
            //移除当前节点
            list.remove(curr);
        }
        for (Vertex vertex1 : graph) {
            System.out.println(vertex1.name+"  "+vertex1.dist +"  "+(vertex1.pre==null?"null":vertex1.pre.name));
        }
    }

    private static void updateNeighboursDist(Vertex curr, ArrayList<Vertex> list) {
        for (Edge edge : curr.edges) {
            Vertex n=edge.vertex;
            if(list.contains(n)){
                int dist= curr.dist+edge.weight;
                if(dist<n.dist){
                    n.dist=dist;
                    n.pre=curr;
                }
            }
        }
    }

    private static Vertex chooseMinDistVertex(ArrayList<Vertex> list) {
        Vertex min=list.get(0);
        for(int i=0;i<list.size();i++){
            if(list.get(i).dist<min.dist){
                min=list.get(i);
            }
        }
        return min;
    }
}

四、改进的迪杰斯特拉算法

        我们发现每次寻找最小值的时候都需要遍历整个集合,时间复杂度为O(n),因此,我们可以用优先队列来解决,优先队列会自动将优先级别高的排在前面,所以,我们只需要将其设置为边的权重越小优先级越高即可,每次只需要取出队首元素即可,时间复杂度为O(1)。

        代码:

package graph;

import java.util.*;

/**
 * 第二种算法的实现:采用优先级队列,减少选取最小距离时的时间复杂度,使用优先级队列直接获取头部元素
 * 时间复杂度得到了改善
 */
public class DijkstraTwo {
    public static void main(String[] args) {
        Vertex v1=new Vertex("v1",new LinkedList<>());
        Vertex v2=new Vertex("v2",new LinkedList<>());
        Vertex v3=new Vertex("v3",new LinkedList<>());
        Vertex v4=new Vertex("v4",new LinkedList<>());
        Vertex v5=new Vertex("v5",new LinkedList<>());
        Vertex v6=new Vertex("v6",new LinkedList<>());

        v1.edges.add(new Edge(v3,9));
        v1.edges.add(new Edge(v2,7));
        v1.edges.add(new Edge(v6,14));

        v2.edges.add(new Edge(v4,15));

        v3.edges.add(new Edge(v4,11));
        v3.edges.add(new Edge(v6,2));

        v4.edges.add(new Edge(v5,6));

        v6.edges.add(new Edge(v5,9));

        List<Vertex> graph=new ArrayList<>();
        graph.add(v1);
        graph.add(v2);
        graph.add(v3);
        graph.add(v4);
        graph.add(v5);
        graph.add(v6);

        dijkstra(graph,v1);
    }

    private static void dijkstra(List<Vertex> graph,Vertex vertex) {
        PriorityQueue<Vertex> queue=new PriorityQueue<>(Comparator.comparing(v->v.dist));//优先级队列,按照距离来升序排列
        for (Vertex vertex1 : graph) {
            queue.offer(vertex1);
        }
        vertex.dist=0;
        while(!queue.isEmpty()){
            //选取当前顶点(距离最小的顶点)
            Vertex curr=queue.peek();
            //更新当前顶点邻居距离
            updateNeighboursDist(curr,queue);
            //移除当前节点
            queue.poll();
            curr.flag=true;
        }
        for (Vertex vertex1 : graph) {
            System.out.println(vertex1.name+"  "+vertex1.dist +"  "+(vertex1.pre==null?"null":vertex1.pre.name));
        }
    }

    private static void updateNeighboursDist(Vertex curr, PriorityQueue<Vertex> queue) {
        for (Edge edge : curr.edges) {
            Vertex n=edge.vertex;
            if(queue.contains(n)){
                int dist= curr.dist+edge.weight;
                if(dist<n.dist){
                    n.dist=dist;
                    n.pre=curr;
                    queue.offer(n);
                }
            }
        }
    }
}

五、贝尔曼福特算法

        贝尔曼福特算法是以边为元素来考虑的,每次从所有边中,找出最小的,并尝试更改边两边结点的最短距离,如果小于原先值就修改,否则就不变。

        算法需要执行(边数-1)次,每次对所有的边上的进行尝试更改。

        代码:

package graph;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

/**
 * 迪杰斯特拉算法不适合存在负值边的情况,
 * 而贝尔曼福特算法能够解决这种问题,是以边为元素来处理的
 */
public class BellmanFord {
    public static void main(String[] args) {
        Vertex v1=new Vertex("v1",new LinkedList<>());
        Vertex v2=new Vertex("v2",new LinkedList<>());
        Vertex v3=new Vertex("v3",new LinkedList<>());
        Vertex v4=new Vertex("v4",new LinkedList<>());
        Vertex v5=new Vertex("v5",new LinkedList<>());
        Vertex v6=new Vertex("v6",new LinkedList<>());

        v1.edges.add(new Edge(v3,9));
        v1.edges.add(new Edge(v2,7));
        v1.edges.add(new Edge(v6,14));

        v2.edges.add(new Edge(v4,15));

        v3.edges.add(new Edge(v4,11));
        v3.edges.add(new Edge(v6,2));

        v4.edges.add(new Edge(v5,6));

        v6.edges.add(new Edge(v5,9));

        List<Vertex> graph=new ArrayList<>();
        graph.add(v1);
        graph.add(v2);
        graph.add(v3);
        graph.add(v4);
        graph.add(v5);
        graph.add(v6);

        bellmanFord(graph,v1);
    }

    private static void bellmanFord(List<Vertex> graph, Vertex v1) {
        v1.dist=0;
        int size=graph.size();
        for(int i=0;i<size-1;i++){//循环边数-1次,找出除了根节点外的其他节点
            //遍历所有的边
            for (Vertex s : graph) {
                for (Edge edge : s.edges) {
                    //处理每一条边
                    Vertex e = edge.vertex;
                    if(s.dist!=Integer.MAX_VALUE && s.dist+edge.weight<e.dist){
                        e.dist=s.dist+edge.weight;
                    }
                }
            }
        }
        for (Vertex vertex : graph) {
            System.out.println(vertex.name+" "+vertex.dist);
        }
    }
}

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

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

相关文章

基于SSM的植物园管理系统设计与实现

目 录 摘 要 I Abstract II 引 言 1 1 开发技术简介 3 1.1 SSM框架 3 1.2 JSON 3 1.3 Ajax 4 1.4 Bootstrap前台框架 4 1.5 Eclipse 4 1.6 本章小结 4 2 系统分析 5 2.1可行性分析 5 2.1.1 技术可行性 5 2.1.2 经济可行性 5 2.1.3 操作可行性 5 2.2 功能需求 5 2.3 用例分析 6…

洞悉 Kubernetes 高阶奥秘:掌控资源、网络、存储,玩转容器化应用!

昨天我们已经入门了K8S&#xff0c;今天带大家学习一下资源、网络、存储这几个进阶的知识点模块内容。这几天陆陆续续会把K8S从头到尾讲一遍&#xff0c;最后会带大家实战一下&#xff0c;下面就开始今天的学习吧。 高级资源和控制器 Kubernetes 提供了一系列高级资源和控制器…

请编程输出无向无权图各个顶点的度 ← 链式前向星存图

【题目描述】请利用链式前向星存图&#xff0c;编程输出无向无权图各个顶点的度。【输入样例】 5 6 1 3 2 1 1 4 2 3 3 4 5 1【输出样例】 4 2 3 2 1【算法分析】 本例需要用到基于链式前向星的广度优先搜索&#xff08;BFS&#xff09;。 链式前向星广度优先搜索&#xff08;B…

JavaScript 实现飞机大战

文章目录 一些关键点概览&#xff1a;核心模块的具体实现示例&#xff1a;飞机类&#xff08;Plane&#xff09;的基本结构&#xff1a;子弹类&#xff08;Bullet&#xff09;的基本结构&#xff1a;敌机类&#xff08;Enemy&#xff09;的基本结构&#xff1a; 基于前面定义的…

Idea创建Maven项目

Maven安装配置步骤&#xff1a; 解压安装 bin目录 &#xff1a; 存放的是可执行命令。&#xff08;mvn 命令重点关注&#xff09; conf目录 &#xff1a;存放Maven的配置文件。&#xff08;settings.xml配置文件后期需要修改&#xff09; lib目录 &#xff1a;存放Maven依赖的j…

Python快速入门系列-2(Python的安装与环境设置)

第二章&#xff1a;Python的安装与环境设置 2.1 Python的下载与安装2.1.1 访问Python官网2.1.2 安装Python对于Windows用户对于macOS用户对于Linux用户 2.2 集成开发环境&#xff08;IDE&#xff09;的选择与设置2.2.1 PyCharm2.2.2 Visual Studio Code2.2.3 Jupyter Notebook2…

bat文件给多个Android设备安装apk

本文是安装一个apk 1、确保以下3个文件在同一个目录下 1>要安装的apk&#xff0c;这里是mmb.apk 2>设备名单&#xff0c;保存在.txt文件中&#xff0c;一行一个设备名&#xff0c;设备名通过adb devices获取&#xff0c;截图中是两个设备 txt文件中的样式 3>要运行…

基于springboot实现大学外卖管理系统项目【项目源码+论文说明】

基于springboot实现大学外卖管理系统演示 摘要 如今&#xff0c;信息化不断的高速发展&#xff0c;社会也跟着不断进步&#xff0c;现今的社会&#xff0c;各种工作都离不开信息化技术&#xff0c;更离不开电脑的管理。信息化技术也越来越渗透到各小型的企业和公司中&#xff…

AI 资讯 | GPT-4 时代终结!Claude 3 一举成为地表最强 AI 模型,今天就能用上!

AI 的飞速发展&#xff0c;对开发者而言意义重大。为此&#xff0c;我们精心筛选了最新 AI 相关资讯与大家分享交流。 未来&#xff0c;Apifox 也将时刻关注 AI 领域发展动态&#xff0c;及时呈现全面的 AI 资讯&#xff0c;与大家一起把握 AI 机遇。希望 在这些资讯中&#xf…

3.9Code

基于顺序存储结构的图书信息表的图书去重 #include<iostream> #include<stdlib.h> #include<string.h>typedef int status;#define OK 1using namespace std;typedef struct{char no[50];char name[50];float price; }Book;typedef struct{Book* elem;int …

J8 - Inception v1算法

目录 理论知识Inception卷积计算 模型结构模型实现inception 结构GoogLeNet模型打印模型结构 模型效果总结与心得体会 理论知识 GoogLeNet首次出现就在2014年的ILSVRC比赛中获得冠军&#xff0c;最初的版本为InceptionV1。共有22层深&#xff0c;参数量5M。 可以达到同时期VGG…

【C++进阶】哈希的应用 --- 布隆过滤器

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前学习C和算法 ✈️专栏&#xff1a;C航路 &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章对你有帮助的话 欢迎 评论&#x1f4ac; 点赞&#x1…

申请公众号上限是多少

一般可以申请多少个公众号&#xff1f;公众号申请限额在过去几年内的经历了很多变化。对公众号申请限额进行调整是出于多种原因&#xff0c;确保公众号内容的质量和合规性。企业公众号的申请数量从50个到5个最后到2个&#xff0c;对于新媒体公司来说&#xff0c;这导致做不了公…

七、软考-系统架构设计师笔记-数据库设计基础知识

1、数据库基础概念 数据库基本概念 数据(Data)数据库(Database)数据库管理系统(DBMS)数据库系统(DBS) 1.数据(Data) 是数据库中存储的基本对象&#xff0c;是描述事物的符号记录。 数据的种类&#xff1a; 文本、图形、图像、音频、视频等。 2.数据库(Database, DB) 数据库…

【Python+Selenium学习系列5】Selenium特殊元素定位之-鼠标悬停操作

前言 Selenium模拟用户在浏览器中的操作&#xff0c;比如点击按钮。在某些场景下&#xff0c;我们需要模拟鼠标悬停的操作&#xff0c;来触发一些隐藏的元素。本文将介绍Python Selenium实现鼠标悬停操作。 鼠标悬停&#xff0c;即当光标与其名称表示的元素重叠时触发的事件&…

菜鸟笔记-14Python绘图颜色使用

Python中绘图主要依赖于各种库&#xff0c;其中matplotlib是最常用且功能强大的一个。在matplotlib中&#xff0c;你可以使用各种颜色来表示不同的数据点、线条或填充区域。下面我将详细介绍如何在Python中使用matplotlib来设置绘图颜色&#xff0c;并给出具体的例子。 14.1颜…

HTML5:七天学会基础动画网页10

继续介绍3D转换: 3D转换:rotate3d 方法与说明 rrotateX(angle)otate3d(x,y,z,angle[角度]) 3D转换&#xff0c;正常取值0/1&#xff0c;0代表当前轴线不进行旋转&#xff0c;1反之&#xff0c;例:rotate3d(1,1,1,30deg)&#xff0c;代表三个轴线都要旋转30度 rotate3d(0…

.text .data .bss .stack 和 heap

.text .data .bss .stack 和 heap 1.1 代码->可执行文件1.2 ELF可执行文件的结构1.3 内存区域1.4 各段在内存中的位置 1.1 代码->可执行文件 一个程序从代码到可执行文件的过程&#xff0c;包括 预处理、编译、汇编&#xff0c;链接。可执行文件有多重类型&#xff0c;有…

深入解读可视化运维的内容、领域、价值和系统搭建

大家好&#xff0c;我是贝格前端工场&#xff0c;接触过很多可视化运维项目&#xff0c;包括IT、电力、物流、生产制造等&#xff0c;本文系统总结一下可视化运维相关知识&#xff0c;老规矩别忘了关注转发&#xff0c;有事请私信。 一、可视化运维定义 可视化运维是指通过可视…

寻找完全平方数——浮点数陷阱

【题目描述】 输出所有形如aabb的4位完全平方数&#xff08;即前两位数字相等&#xff0c;后两位数字也相等&#xff09;。 【解析】 一、问题分析 从问题出发&#xff0c;题目要求输出的是满足一定条件的数。数在计算机中是要占存储空间的&#xff0c;要在计算机中表示一个…
最新文章