数据结构8——最短路径

一、最短路径

最短路径:从图中的某个顶点出发到达另外一个顶点的所经过的边的权重和最小的一条路径。

  1. Dijkstra算法
  2. Bellman-Ford算法
  3. Floyd算法
  4. SPFA算法

二、负权问题

如果一个图仅仅是存在负权,但不构成负权回路,又该如何?

  • Dijkstra 算法

观察上图,若 A 作为源点,在第一轮循环后,B 被标记数组标记,但我们发现在第二轮循环中,B 还可以通过 C 点继续进行更新。由此,可以得出结论:Dijkstra 算法不适用于负权图。

  • Bellman_Ford 算法和 SPFA 算法

我们先思考下上述 “因 B 点被标记数组标记而导致无法通过 C 点再更新” 的问题,归根结底是标记数组的锅。有人提议,不妨去掉标记数组,如果去掉,就会造成很严重的问题,首当其冲的是“无法求出dist[]的最小值”。

反观 Bellman_Ford 算法和 SPFA 算法,它们不存在标记数组的问题,因此对于仅仅存在负权的图,它们都可以工作的很好。

最后,读者需要注意的是,如果是无向图,只要存在一条负边,该图就存在负权回路,这不难理解,无向图的一条边相当于有向图的往返两条边。

Dijkstra,Bellman_Ford 和 SPFA,该用哪个?

Bellman_Ford 没什么好说的,能不用就不用。

国际上一般不承认 SPFA 算法,因为在 SPFA 算法论文中对它的复杂度证明存在错误,其次 Bellman_Ford 的论文中已提及过这个队列优化。

SPFA 算法有两个优化策略 SLF 和 LLL。

  • SLF,Small Label First 策略,设要加入的节点是 j,队首元素为 i,若dist[j] < dist[i],则将 j 插入队首,否则插入队尾;
  • LLL,Large Label Last 策略,设队首元素为 i,队列中所有 dist 值的平均值为 x,若dist[i] > x则将 i 插入到队尾,查找下一元素,直到找到某一 i 使得dist[i] <= x,则将 i 出队进行松弛操作。

SLF 可使速度提高 15 ~ 20%,SLF + LLL 可提高约 50%。 在实际的应用中 SPFA 的算法时间效率不是很稳定,为了避免最坏情况的出现,通常使用效率更加稳定的 Dijkstra 算法。

使用邻接表 + 二叉堆优化的 Dijkstra 算法,复杂度适宜,也稳定,就是有个缺陷,不能处理负权回路。

最后话个唠,我发现在算法竞赛中我们大多数的选择还是 SPFA,知乎了下,邻接表 + 二叉堆优化的 Dijkstra 写起来复杂,容易错,而 SPFA 代码简单,容易写,但是会被题目卡数据。

总结:首选 Dijkstra,其次 SPFA,最后 Bellman_Ford,具体采用哪种方法,视情况而定。

时间: 2024-08-29 00:09:16

数据结构8——最短路径的相关文章

数据结构——图——最短路径D&amp;F算法

一.Dijkstra算法(贪心地求最短距离的算法) 在此算法中,我按照自己的理解去命名,理解起来会轻松一些. #define MAXSIZE 100 #define UNVISITED 0 #define VISITED 1 #define INFINITY 66666 typedef struct tool { int visited[MAXSIZE]; /*是否已访问的数组,visited[i]表示顶点i已经访问,也就是到顶点i的最短距离已求出*/ int known_shortest_di

数据结构10——最短路径

最短路径:带权图中从一个结点到另外一个结点可能会有多个路径,但是将带权路径长度值最小的一条路径成为最短路径. 1:(Dijkastra)迪克斯特拉算法: 迪克斯特拉算法用于最短路径的方法和prim用于最小生成树的方法类似都是按照路径权值由小到大的顺序来产生最短路径. 主要思想:设置两个集合的结点S和T,集合S用于存放已经找到最短路径的结点, 集合T中存放当前未找到的最短路径. 与前面的prim算法类似都是通过路径逐渐递增的方式来获得. 迪克斯特拉算法的具体实现: 1 package com.ho

数据结构之最短路径(1) [迪杰斯特拉算法]

迪杰斯特拉算法介绍: 迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径. 它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止. 基本思想: 通过Dijkstra计算图G中的最短路径时,需要指定起点s(即从顶点s开始计算). 此外,引进两个集合S和U.S的作用是记录已求出最短路径的顶点(以及相应的最短路径长度),而U则是记录还未求出最短路径的顶点(以及该顶点到起点s的距离). 初始时,S中只有起点s:U中是除s之外的顶点,并且

最短路径之差分约束

一.前言 本文的目的是探讨最短路径与差分约束之间的关系.为了方便理解,本文将从存储图的数据结构,最短路径的算法,以及最短路径算法和差分约束之间的相互转换关系来讨论.而基于最短路径的有一个著名的三角形不等式,即两边之和大于第三边或者两边只差小于第三边,a+b>c和a-b<c. 图的存储结构 工欲善其事必先利其器,为了更好的理解最短路径,必须先了解存储图的数据结构. 一般而言,图的存储方式,有按节点存储按边存储两种方式. 传统来说,按节点存储的是临接矩阵存储方式,优点是实现简单,一个二维数组就能实

数据结构:单源最短路径--Dijkstra算法

Dijkstra算法 单源最短路径 给定一带权图,图中每条边的权值是非负的,代表着两顶点之间的距离.指定图中的一顶点为源点,找出源点到其它顶点的最短路径和其长度的问题,即是单源最短路径问题. Dijkstra算法 求解单源最短路径问题的常用方法是Dijkstra(迪杰斯特拉)算法.该算法使用的是贪心策略:每次都找出剩余顶点中与源点距离最近的一个顶点. 算法思想 带权图G=<V,E>,令S为已确定了最短路径顶点的集合,则可用V-S表示剩余未确定最短路径顶点的集合.假设V0是源点,则初始 S={V

Java数据结构 最短路径解法Dijkstra算法

本文为博主原创文章,未经博主允许不得转载! 1.1.定义概览Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.Dijkstra算法是很有代表性的最短路径算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹学等等.注意该算法要求图中不存在负权边. 问题描述:在无向图 G=(V,E) 中,假设每条边 E[i] 的长度为 w[i],找到由顶点 V0 到其余各点的最短路径.(

数据结构 -- 图的最短路径 Java版

作者版权所有,转载请注明出处,多谢.http://www.cnblogs.com/Henvealf/p/5574455.html 上一篇介绍了有关图的表示和遍历实现.数据结构 -- 简单图的实现与遍历 (Java)现在就来看看关于求图的最短路径的问题: 注意:本人学习图的时候看的书是: <<数据结构与算法 Java语言版>> (美)Adam Drozdek/著 周翔/译 机械工业出版社出版 由于要仔细讲解内容过多并且本人水平有限,推荐大家找出这本书来看,本篇文章主要是对其中Dijk

数据结构实践项目——最短路径和拓扑序列

本文是针对[数据结构基础系列(7):图]的第2组实践例程. (程序中graph.h是图存储结构的"算法库"中的头文件,详情请单击链接-) 0710 生成树的概念 0711 最小生成树的普里姆算法 0712 最小生成树的克鲁斯卡尔算法 0713 从一个顶点到其余各顶点的最短路径 0714 每对顶点之间的最短路径 0715 拓扑排序 0716 AOE网与关键路径 纸上谈兵:"知原理"检验题目 1.针对下面的图1: (图1) (1)写出图的邻接矩阵: (2)按照Prim算

43. 蛤蟆的数据结构笔记之四十三最短路径之迪杰斯特拉(Dijkstra )算法

43. 蛤蟆的数据结构笔记之四十三最短路径之迪杰斯特拉(Dijkstra )算法 本篇名言:"辛勤的蜜蜂永没有时间悲哀.--布莱克" 这次来看下Dijkstra )算法.还是老方法,先原理,后实现.代码来自网络. 欢迎转载,转载请标明出处:http://blog.csdn.net/notbaron/article/details/47046031 1.  最短路径 最短路径问题是图论研究中的一个经典算法问题, 旨在寻找图(由结点和路径组成的)中两结点之间的最短路径. 管道铺设.线路安排