数据结构和算法-最短路径

针对无权图可以使用深度优先和广度优先算法, 有权图可以使用最短路径算法

Dijkstra(迪杰斯特拉算法): 在有向加权图中查找最短路径

注意: 该算法只适用于有向无环图, 不适用于负权边的情况

思路:

  1. 找出距离起点最近的节点
  2. 对于该节点邻居, 检查是否有前往他们的更短路径, 如果有就更新开销
  3. 重复以上两步, 直到所有节点运行过
  4. 找出最短路径

下表为要从起点到达终点, 数字为花费的时间

父节点 节点 花费
start A 6
start B 2
B A 5
B end 7
A end 6

上图是按照以上步骤进行填充的

  1. 找出start的邻居节点AB, 其中B的花费最少
  2. 找出B节点的邻居节点Aend, 更新到A节点的开销
  3. 继续对A节点进行, 从Aend花费最小, 更新Bend的开销

所以最小距离为start --> B --> A --> end

实现

利用最小堆实现, 时间复杂度: O(e * logv), e是边的个数

# -*- coding:utf-8 -*-

'''
Dijkstra算法(最短路径算法)

- 适用于有向有权无环图
- 不适用于负权边的情况
'''

import heapq

class Graph(object):
    def __init__(self):
        self.graph = {}

    def add_edge(self, start: str, end: str, distance: float):
        self.graph.setdefault(start, {})
        self.graph[start][end] = distance

def dijkstra(start: str, end: str, graph: dict) -> list:
    visited = set()  # 存储已经处理过的节点
    costs = {start: 0}

    queue = [(0, start)]
    path = {}  # 用于复原路径

    while queue:
        dis, min_node = heapq.heappop(queue)
        if min_node == end:
            break

        if min_node not in visited:
            visited.add(min_node)

            neighbors = graph[min_node]
            for i, j in neighbors.items():
                new_dis = dis + j
                if (i not in costs) or (new_dis < costs[i]):
                    costs[i] = new_dis
                    heapq.heappush(queue, (new_dis, i))
                    path[i] = min_node

    res = []
    key = end
    while key != start:
        res.append(key)
        key = path[key]
    res.append(start)
    res.reverse()

    return res

if __name__ == '__main__':
    g1 = Graph()
    g1.add_edge('start', 'a', 3)
    g1.add_edge('start', 'b', 2)
    g1.add_edge('b', 'a', 6)
    g1.add_edge('b', 'end', 5)
    g1.add_edge('a', 'end', 1)
    assert dijkstra('start', 'end', g1.graph) == ['start', 'a', 'end']

    g2 = Graph()
    g2.add_edge('start', 'a', 5)
    g2.add_edge('start', 'b', 2)
    g2.add_edge('b', 'a', 1)
    g2.add_edge('b', 'end', 5)
    g2.add_edge('a', 'end', 1)
    assert dijkstra('start', 'end', g2.graph) == ['start', 'b', 'a', 'end']
  • 利用最小堆不断找出开销最小的节点
  • 当发现有到达某个节点的更短距离是更新该节点的距离

资料

  • <>
  • <>

原文地址:https://www.cnblogs.com/zlone/p/11013606.html

时间: 2024-10-08 07:43:30

数据结构和算法-最短路径的相关文章

数据结构与算法——最短路径Dijkstra算法的C++实现

之前的讨论了无权图的最短路径算法.数据结构与算法--无权最短路径算法的C++实现 如果是加权图,那么问题就变得困难了,不过仍然可以采用无权情况的想法. 我们仍然保留之前的信息.因此,每个顶点会被标记为known或unknown,每个顶点保留一个尝试性的距离dv(这个距离是只使用一些known顶点作为中间顶点从s到v的最短路径的长),每个顶点还保留字段pv,该字段是记录引起dv变化的最后的顶点. 图顶点信息的数据结构: //保存每个顶点信息的数据结构 struct GraphNode{ bool

数据结构与算法问题 单源最短路径 浙大OJ

题目描述: 给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的. 输入: 输入n,m,点的编号是1~n,然后是m行,每行4个数 a,b,d,p,表示a和b之间有一条边,且其长度为d,花费为p.最后一行是两个数 s,t;起点s,终点t.n和m为0时输入结束. (1<n<=1000, 0<m<100000, s != t) 输出: 输出 一行有两个数, 最短距离及其花费. 样例输入: 3 2

数据结构与算法——无权最短路径算法的C++实现

对于一个有权图,任意路径中各个边的权重的和,就是加权路径长. 对于一个无权图,任意路径中边的数目,就是无权路径长. 对于上面的无权图G,我们使用某个顶点s作为输入参数,我们想要找出从s到所有其它顶点的最短路径.我们只对路径上边的数目感兴趣,不考虑路径上边的权重(对于无权图可以将权重看为是1). 算法1详细步骤: 1.选择顶点s为v3.马上可以知道s到v3的最短路径长为0的路径(v3->v3) 2.寻找从s出发路径长为1的顶点,这些点都是s的邻接点. 3.寻找从s出发路径长为2的顶点.找到v1和v

数据结构与算法 第四次实验报告 图

数据结构与算法 第四次实验报告 姓名:许恺 学号:2014011329 班级:计算机14-1     中国石油大学(北京)计算机科学与技术系 1.图的定义,文件为"Graph.h" #ifndef GRAPH_H//定义头文件 #define GRAPH_H #include<string>//引入标准库中的头文件 using namespace std; const int MaxSize=12; struct ArcNode//定义边表结点 { int adjvex;/

数据结构与算法知识大纲

数据结构与算法 1.线性结构 (1)线性表 ①线性表的定义 ②线性表的存储结构 ③线性表的应用 (2)栈和队列 ①栈 ②队列 (3)串 ①串的定义及基本运算 ②串的存储结构 2.数组和矩阵 (1)数组 (2)矩阵 3.树和图 (1)树 ①树的定义 ②二叉树的定义和基本运算 ③二叉树的性质 ④二叉树的存储结构 ⑤二叉树的遍历 ⑥最优二叉树 ⑦二叉查找树 (2)图 ①图的定义及术语 ②图的存储结构 4.常用算法 (1)算法概述 ①算法的基本概念 ②算法与数据结构 ③算法的描述 ④算法效率 (2)排序

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

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

大数据就是这么任性第一季数据结构和算法(一线经验、权威资料、知识新鲜、实践性强、全程源码)

这门课程是针对大数据工程师和云计算工程师的基础课程,同时也是所有计算机专业人士必须掌握的一门课程. 如果不掌握数据结构和算法,你将难以掌握高效.专业的数据处理手段,更难以从容应对复杂的大数据处理场景. 请思考以下问题: 1.社交网站(如微博.facebook)中,人与人的关系是海量数据,你如何研究和处理此问题? 2.数据库的索引作用是什么?为什么利用哈希.B+树和堆表等数据结构来组织索引? 3.为什么Linux的虚拟内存管理模块,使用红黑树来处理VMA的查找? 4.为什么搜索引擎可以在毫秒级返回

java常用的数组、字符串、集合操作以及数据结构与算法基本知识

java中常用封装的数组 .字符串. 集合来操作对象,但数据结构中常用的有栈和队列   数与图以及他们之间的排序,查找. 数组声明没有分配内存空间  只有创建或者是初始化时才分配,创建时把数组中的数据类型数据所在的内存空间首地址赋值给数组名,在创建每个对象时,都会给该对象分配地址和它存储的数据 .如变量    int arr[]; int arr[]={1,2,3};  arr=new int[10] ,int arr[][]={{1,9,7},{1,2,3}}  int arr[][]=new

用python语言讲解数据结构与算法总述(一)

关于数据结构与算法讲解的书籍很多,但是用python语言去实现的不是很多,最近有幸看到一本这样的书籍,由Brad Miller and David Ranum编写的<Problem Solving with Algorithms and Data Structures Using Python>,地址为:http://interactivepython.org/runestone/static/pythonds/index.html是英文的,写的不错,里面代码的实现也很详细,很多有趣的例子,于