最短路径算法—Dijkstra算法和BellmanFord算法

算法4第4章加权有向图Dijkstra/BellmanFord最短路径算法关键路径算法讲解 最短路径即从一个顶点到达另一个顶点成本最小的路径,例如利用导航软件获取从一个地方到达另一个地方的路径,顶点对应路口,边对应公路,边的权重对应经过该路段的成本,可以是时间或距离,如果有单行线,那就要考虑加权有向图。 加权有向图的数据结构实现如下 public class EdgeWeightedDigraph { private static final String NEWLINE =... 阅读详情

松弛操作

Dijkstra算法和BellmanFord算法都是基于这个简单的操作。
下面我们来了解这个简单而重要的操作:

  1. 线松弛
    线松弛也就是处理
    起点到边的两个顶点距离与两个顶点直接距离的问题。
    如:假如distTo[4]>distTo[3]+e.weight(),则会修改到达4顶点的最短路径,否则不变。
    边松弛

2.点松弛
点松弛其实就是对顶点的每一条发出的边都进行一次线松弛操作。
如图:边3->2,同样要进行线松弛。
点松弛

Dijkstra算法

直接附上代码了(有详细解释)
性能:任何情况下都能保证较好的性能(当然,此算法不能存在负值的边)

package ShortestPath;

import java.util.Stack;

/**
  *基于解决加非负权值有向图的单起点的最短路径问题Dijkstra算法
  *该类维护了三个变量:{@link DirectedEdge}类数组{@link path};{@link double}数组{@link distTo};{@link IndexMinPQ}优先队列{@link pq}
  *<p>其中path保存了到达某个顶点的最短路径;distTo[w]:起点到w的权值和(初始都为0,起点除外);pq:保存了顶点的优先队列
  *<p>算法思想:每次都为最短路径增加一条边,直至涵盖所有的顶点或者非树顶点的distTo都为无穷大的时候结束。
  * @author  罗正 
  * @date 2016年9月23日 上午9:41:42 
**/
public class DijkstraSP {

    private IndexMinPQ<Double> pq;  //顶点的优先队列
    private double[] distTo;    //每个顶点的距离(初始化为无穷大)
    private DirectedEdge[] path;    //保存了关键路径的边

    /**
     * 构造的Dijkstra函数,传入带权值无向图g,以及起点s
     * */
    public DijkstraSP(EdgeDigraph g,int s)
    {
        //初始化
        distTo = new double[g.V()];
        pq = new IndexMinPQ<Double>(g.V());
        path = new DirectedEdge[g.V()];

        //将所有顶点与起点的距离都初始化为无穷大
        for(int v = 0;v<g.V();v++)
            distTo[v] = Double.POSITIVE_INFINITY;
        //将起点距离设置为0,并加入到优先队列中
        distTo[s] = 0.0;
        pq.insert(s, 0.0);
        while(!pq.isEmpty())
        {
            relax(g,pq.delMin());
        }

    }

    /**
     * 最短路径的关键方法:边的松弛(relaxation)
     * <p>该方法会维护所有v到达的边(即以v为起点的边),假设存在v->w(非树):
     * 首先方法会循环到v->w这条边;
     * <p>假若:起点到w的距离(distTo[w])比起点到达v的距离(distTo[v])和v->w的边((v->w).weight())还要大的话;
     * <p>那么是不是对于求最短路径来说,到达w顶点的路径是不是就要变成先到达v再由v到达w呢,这是显然的。
     * @param g
     * @param v
     */
    private void relax(EdgeDigraph g,int v)
    {
        for(DirectedEdge e : g.adj(v))
        {
            int w = e.to();
            if(distTo[w]>distTo[v]+e.weight())
            {
                distTo[w] = distTo[v]+e.weight();
                path[w] = e;
                /*假如w已经包含在最短路径中,也还是要修改到达w的路径的,因为已经更短了啊*/
                if(pq.contains(w))
                    pq.change(w, distTo[w]);
                else
                    pq.insert(w, distTo[w]);
            }
        }
    }

    public double distto(int v)
    {
        return distTo[v];
    }

    public boolean hasPath(int v)
    {
        return distTo[v]<Double.POSITIVE_INFINITY;
    }

    public Iterable<DirectedEdge> path(int v)
    {
        if(!hasPath(v))
            return null;
        else
        {
            Stack<DirectedEdge> pathTo = new Stack<>();
            for(DirectedEdge e = path[v];e != null; e = path[e.from()])
                pathTo.push(e);
            return pathTo;
        }
    }

    public static void main(String[] args) {
        DirectedEdge e1 = new DirectedEdge(0, 1, 100);
        DirectedEdge e2 = new DirectedEdge(1, 3, 200);
        DirectedEdge e3 = new DirectedEdge(0, 2, 200);
        DirectedEdge e4 = new DirectedEdge(2, 3, 200);
        EdgeDigraph g = new EdgeDigraph(4);
        g.addEdge(e1);
        g.addEdge(e2);
        g.addEdge(e3);
        g.addEdge(e4);

        DijkstraSP dij = new DijkstraSP(g, 0);
        System.out.println(dij.path(3));
    }

}

Bellman—Ford 算法


这里讨论的是基于队列的BellmanFord算法的实现。

此算法适用于任何情况(当然,存在负权值环对于求最短路径是没有意义的。)

package ShortestPath;

import java.util.ArrayDeque;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;

import minSpanningTree.Edge;

/**
  *基于队列的Bellman-Ford算法: 将起点的distTo[s]初始为0,将其他所有顶点distTo初始为无穷大,任意顺序放松所有边,重复V轮。
  *<p>思路:与Dijkstra算法类似,double数组distTo意义一样;
  *队列queue保存放松的顶点;不同的是增加一个标记标记重复每轮放松的顶点和下一轮放松的顶点(使得队列不会重复保存顶点),下轮在放松函数里设置为true,以便保证下轮不重复;
  *Bellman—Ford算法对于一般加权值图,其中就包括了负值权值(但是假若存在负权值的环,则对于求最短路径则没有意义了)
  *<p>1>首先明白为什么存在负权值换对于求最短路径没有意义?因为在环里每重复一次,我们都能得到一条更短的路径。
  *<p>2>加入存在负权值环,relax过程会有什么异常呢?由上一个问题答案,我们知道,这个过程假如和Dijstra算法无异,则会无限循环下去
  *<p>3>如何确定存在负权值环呢?我们前面已经知道,重复V轮,我们就能得到最短路径,
  *事实上我们只需要V-1轮结束后,就能得到最短路径,所以,假如重复了V轮,是不是就说明存在负权值环了呢
  *
  * @author  罗正 
  * @date 2016年9月23日 下午3:40:23 
**/
public class BellmanFordSP {

    private double[] distTo;
    private boolean[] onQ;
    private DirectedEdge[] edgeTo;
    private Queue<Integer> queue;

    //对于检测负权值环定义的变量
    private int count;
    private Iterable<DirectedEdge> cycle;

    /**
     * 此函数和Dijkstra算法的函数并无太大区别,只是增加了onQ[],标记顶点。
     * @param g
     * @param s
     */
    public BellmanFordSP(EdgeDigraph g,int s)
    {
        distTo = new double[g.V()];
        onQ = new boolean[g.V()];
        int count = 0;
        queue = new ArrayDeque<>();
        edgeTo = new DirectedEdge[g.V()];

        for(int i = 0;i<g.V();i++)
            distTo[i] = Double.POSITIVE_INFINITY;

        distTo[s] = 0.0;
        onQ[s] = true;
        queue.add(s);
        while(!queue.isEmpty())
        {
            int v = queue.remove();
            onQ[v] = false;
            relax(g,v);
        }
    }

    /*放松操作*/
    private void relax(EdgeDigraph g,int v)
    {
        for(DirectedEdge e : g.adj(v))
        {
            int w = e.to();
            if(distTo[w] > distTo[v]+e.weight())
            {
                distTo[w] = distTo[v]+e.weight();
                edgeTo[w] = e;
                if(!onQ[w])
                {
                    queue.add(w);
                    onQ[w] = true;
                }
            }

            //假如存在环,则count == V
            if(count++ % g.V() == 0)
                findNegativeCycle();
        }
    }

    public double distto(int v)
    {
        return distTo[v];
    }

    public boolean hasPath(int v)
    {
        return distTo[v]<Double.POSITIVE_INFINITY;
    }

    public Iterable<DirectedEdge> path(int v)
    {
        if(!hasPath(v))
            return null;
        else
        {
            Stack<DirectedEdge> pathTo = new Stack<>();
            for(DirectedEdge e = edgeTo[v];e != null; e = edgeTo[e.from()])
                pathTo.push(e);
            return pathTo;
        }
    }

    //检测环函数,并保存环
    private void findNegativeCycle()
    {
        int V = edgeTo.length;
        EdgeDigraph g;
        g = new EdgeDigraph(V);

        for(int v = 0;v<V;v++)
        {
            if(edgeTo[v] != null)
                g.addEdge(edgeTo[v]);
        }

        EdgeWeightedDirectedCycle c = new EdgeWeightedDirectedCycle(g);
        cycle = c.cycle();
    }

    public boolean hasNegativeCycle()
    {
        return cycle == null;
    }

    public Iterable<DirectedEdge> negativeCycle()
    {
        return cycle;
    }
}
[图论]万字解析图的最短路算法(详细带图解和代码) 图的最短路算法图的存储方式领接矩阵领接表最短路算法知识框架单源最短路径路径权值全为正数dijkstra算法(版本1)dijkstra(堆优化版本)路径权值存在负数bellmanFord算法spfa算法(基于bellmanFord的优化)多源最短路径(Floyd算法)参考文章 图的存储方式 图主要有以下两种表示方法:邻接矩阵和邻接表(注意,本文仅讨论有向图的情况) 领接矩阵 假设我们有以下的图 每个圈表示一个图中节点,圈里面的数字表示此节点编号,每个边都有权重 我们可以用一个二维数组存储这个图:设此二维矩阵 阅读详情

相关推荐

【Flink cdc】Data row is smaller than a column index, internal schema representation is probably xxx

翻译一下:当scan.startup.mode=EARLIEST_OFFSET时,如果在最早的offset之后表结构有过变化就无法支持。原因应该是在binlog 的earliest_offset之后,表结构被修改过。我的解决方案:source配置中使用。mysql source配置使用。,以时间戳为消费依据。

integrity 2085

Dijkstra与Bellman-Ford算法对比

Dijkstra与Bellman-Ford的对比

铁血军的小博客 3244

项目风险管理全流程解析

按技术、资源、市场、外部环境等类型对风险进行分类,便于团队快速识别风险,提高风险管理效率,避免风险遗漏。项目结束后,总结实际发生的风险和应对效果,找出风险管理中的经验和教训,为后续项目提供参考。

qq_34062333的博客 1471

图解 Dijkstra、Floyd、BellMan-Ford 最短路径算法

图解 Dijkstra Floyd BellMan-Ford 最短路径算法

weixin_54383080的博客 5720

WPF实战:利用Live Charts实现高性能动态曲线可视化

本文详细介绍了如何在WPF中使用Live Charts实现高性能动态曲线可视化,特别适用于工业监控和金融分析等实时数据场景。通过增量渲染、内存复用和硬件加速等核心技术,Live Charts能够高效处理高频数据更新,显著提升图表流畅度。文章提供了从基础实现到工业级优化的完整解决方案,帮助开发者应对各种性能挑战。

weixin_29189373的博客 408

[RK3568 Android11] 开发之默认授予系统预置的APP权限

目录 一、系统预置的APP权限 二、默认授予系统预置的APP权限 一、系统预置的APP权限 1、在打开系统预置的APP时,都会弹窗提示,并且需要人工确定授予权限; 2、有些客户对定制有需求,需要系统预置的APP自动默认授予权限; 二、默认授予系统预置的APP权限 注意此方法只对系统预置的APP起效果,后期手动安装的APP无效; 修改文件: frameworks/base/services/core/java/com/android/server/pm/per...

~未来可期~ 5059

经典算法研究系列:二、Dijkstra 算法初探

经典算法研究系列:二、Dijkstra 算法初探 July   二零一一年一月本文主要参考:算法导论 第二版、维基百科。一、Dijkstra 算法的介绍    Dijkstra 算法,又叫迪科斯彻算法(Dijkstra),算法解决的是有向图中单个源点到其他顶点的最短路径问题。举例来说,如果图中的顶点表示城市,而边上的权重表示著城市间开车行经的距离,Dijkstra 算法可以用来找到两个城市之间的最

结构之法 算法之道 10万+

【图像超分】论文复现:Pytorch实现SRCNN!保姆级复现教程!提供完整代码和最优权重模型(x2、x3、x4)!科研级论文曲线图!计算平均PSNR和SSIM!代码Windows和Linux都可用!

由于很多同学反应没用过jupyter notebook,更习惯用pycharm项目的形式跑代码。于是,本文将用pycharm项目的形式,重新复现SRCNN!【图像超分】论文复现:新手入门!Pytorch实现SRCNN,数据预处理、模型训练、测试、评估全流程详解,注释详细,简单修改就可以训练你自己的图像数据,有训练好的模型下载地址,随取随用。

主要更新底层视觉(去噪、超分等)相关的科研内容,形式为【论文精读】+【论文复现】 4705

单源节点最短路径蛮力法和Dijkstra算法性能对比

一、单源节点问题的对比         在本文中,考虑单源点最短路径问题,对于一个加权连通图的一个称为起点的给定定点,求出它到所有其他定点之间的一系列最短路径。需要说明的是,这里所关心的不是从一个起点出发访问所有其他定点的单条最短路径,这种问题的难度更大。单起点最短路径问题要求的是一组路径,每条路径都从起点出发通向图中的一个不同顶点,其中某些路径可能具有公共边。在求带权连通图中最短路径问题有两个

wang_dong001的博客 2797

手把手教你学PCIE(2.1.8)--pcie基本概念流量控制(Flow Control, FC)

PCIe 的流量控制(Flow Control, FC)是确保数据传输可靠性和高效性的关键技术。通过信用值管理,发送方和接收方可以动态调整数据传输速率,避免数据丢失和溢出。理解流量控制的工作原理和实现机制对于开发和调试 PCIe 系统非常重要。希望这个介绍能帮助你更好地理解和使用 PCIe 流量控制。

MHD0815的博客 1808

【遥感物候】植被物候与气候(气温和降水)条件的空间相关性分析

植被生长与气候的关系最为密切,通过计算植被各个生长季参数和气温、降水之间的相关系数可以分析生长季参数的变化与气温、降水之间的关系的程度。本文计算30年的植被物候参数和气候数据之间的相关性,最终效果如下: 一、相关性分析原理 植被生长季及其变化是其生长环境中多个影响因子综合作用的耦合过程,其中气候是最重要、最活跃的环境因子。通过计算各个生长季参数和气温、降水之间的相关系数...

智慧空间实验室 8262

Dijkstra算法

Dijkstra(迪杰斯特拉)算法是典型的最短路径路由算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。Dijkstra算法能得出最短路径的最优解,但由于它遍历计算的节点很多,所以效率低。 Dijkstra算法是很有代表性的最短路算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹学等等。 其基本思想是,设置顶点集合S

Ginvar的专栏 483

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

最短路径:Dijkstra、BellmanFord以及SPFA算法

最短路径问题1、Dijkstra算法简介(1)Dijkstra算法伪代码(2)C++ 邻接表版代码(3)优化2、Bellman Ford算法简介(1)Bellman算法伪代码(2)C++ 邻接表版代码3、SPFA算法简介(1)SPFA算法伪代码(2)C++ 邻接表版代码 1、Dijkstra算法 简介 Dijkstra算法用于计算单源最短路径,即给定图G(V,E)以及源点s,求s到其他顶点的最短路径。 时间复杂度: (1)Dijkstra算法伪代码 dijkstra (G,s){ 初始化变量 for 循

努力学习的! 681

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

最短路径算法之 Dijkstra && BellmanFord(模板)

目录1 Dijkstra算法1.1 算法模板1.2 例题Problem DescriptionInput SpecificationOutput SpecificationSample InputSample Output题解2 BellmanFord2.1 讲解2.2 例题问题描述输入格式输出格式样例输入样例输出数据规模与约定题解 1 Dijkstra算法 适用范围:不能解决带有负边的图 1.1 算法模板 #include <iosream> #include <cstdio>

Lili Liang的博客 657

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

有向图的最短路径算法(Dijkstra+BellmanFord+Floyd)

一、最短路径简介        所谓最短路径问题是指:如果从图中某一顶点(源点)到达另一顶点(终点)的路径可能不止一条,如何找到一条路径使得沿此路径上各边的权值总和(称为路径长度)达到最小。        路径规划就是最短路径的典型应用。 二、Dijk...

cj1561435010的博客 8650

最短路径算法--Dijkstra算法,Bellmanford算法,Floyd算法,Johnson算法

最短路径算法 在交通地图上,两地点之间的路径通常标有长度,我们可以用加权有向来描述地图上的交通网。加权有向图中每条路径都有一个路径权值,大小为该路径上所有边的权值之和。本节将重点讨论顶点之间最短路径问题。在实际问题中,路径权值还可以表示其它类型的开销,例如两地之间行程所需要的时间;两任务切换所需代价等。 本节讨论的最短路径具有方向性,问题用图的术语描述为:给定一个起始顶点s和一个结束顶点t,在

happylife1527的专栏 1万+

[Java]-最短路径(Dijkstra,BellmanFord,Topological算法)

最短路径 最短路径描述的是在一幅加权有向图中,从一个顶点s到任意顶点的所有路径中权重最小的一条路径 单点最短路径问题 在一幅加权有向图中,从顶点s到任意顶点v是否存在一条有向路径,如果存在,找出权重最小的那一条有向路径 最短路径树 最短路径树描述的是在一幅加权有向图中,某一顶点s到任意顶点的最短路径组成的树,这棵树的根节点是顶点s,s到树上所有子...

renboyu010214的博客 829

【算法】图的最短路径

本文介绍了三种经典的最短路径算法:Dijkstra算法(单源最短路径,不适用于负权值)、Bellman-Ford算法(单源最短路径,可处理负权值但不支持负权回路)和Floyd算法(双源最短路径)。重点解析了Dijkstra算法的贪心原理,通过集合划分和迭代选取最近顶点的方式实现路径优化,并给出了邻接矩阵实现代码。同时简要说明了Bellman-Ford算法的特点——能处理负权边但无法解决带负权回路的图。文中通过图示详细演示了Dijkstra算法的执行过程。

2403_88316985的博客 802

最短路径算法--DIJKSTRA算法,BELLMANFORD算法,FLOYD算法,JOHNSON算法

最短路径算法 在交通地图上,两地点之间的路径通常标有长度,我们可以用加权有向来描述地图上的交通网。加权有向图中每条路径都有一个路径权值,大小为该路径上所有边的权值之和。本节将重点讨论顶点之间最短路径问题。在实际问题中,路径权值还可以表示其它类型的开销,例如两地之间行程所需要的时间;两任务切换所需代价等。 本节讨论的最短路径具有方向性,问题用图的术语描述为:给定一个起始顶点s和一个结束顶点t,在

MSFollower的博客 830

图论最短路径专题(力扣743、5888)

第八十五天 --- 图论最短路径专题(力扣743、5888)题目一朴素Dijkstra解决无负权边的单源最短路径问题思路代码邻接矩阵邻接表复杂度Floyd解决多源点最短路径问题题目二堆优化Dijkstra解决无负权边的单源最短路径问题思路:自己封装堆代码Bellman Ford算法解决带有负权边或者有限制的最短路径问题SPFA:Bellman Ford算法的优化 题目一 力扣:743. 网络延迟时间 本题其实就是让求各个点到源点最短路,且最短路中要找到最大者。 朴素Dijkstra解决无负权边的单源最

qq_45678698的博客 3872

6.3.3 最短路径算法--Dijkstra算法,Bellmanford算法,Floyd算法,Johnson算法

最短路径算法 在交通地图上,两地点之间的路径通常标有长度,我们可以用加权有向来描述地图上的交通网。加权有向图中每条路径都有一个路径权值,大小为该路径上所有边的权值之和。本节将重点讨论顶点之间最短路径问题。在实际问题中,路径权值还可以表示其它类型的开销,例如两地之间行程所需要的时间;两任务切换所需代价等。 本节讨论的最短路径具有方向性,问题用图的术语描述为:给定一个起始顶点s和一个结束顶点t,在

ajian005的专栏 1578

最短路径_Dijkstra_BellmanFord_SPFA_FloyedWarshall_Johnson

最短路径算法 Dijkstra 核心思想:BFS、贪心 数据结构:两个数组 isShortest[],抵达该点是否已经找到最短路径(保存T/F);初始全F Dis[],抵达该点的距离;初始infinite(除起点); 基本过程: Shortest[1]=T,从1开始“广度优先搜索”,更新Dis[]; 选择isShortest[i]=F且Dis[i]中“值最小”的点(即在未获得最短路径的点集中找“当前路径最小”的点),并将对应isShortest[i]=T,更新Dis数组; 循环上一步至isShort

m0_43408050的博客 262
上一篇: 最小生成树—Prim算法和Kruskal算法
下一篇: Python基础(一)—数值类型和字符类型
luoz_python
博客等级 码龄10年 57粉丝 47原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值