从无名小村落到长春最快多长时间?用Python实现狄克斯特拉算法(迪杰斯特拉算法、迪克斯特拉算法)

狄克斯特拉算法介绍

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

2.算法描述
(1)算法思想:设G=(V,E)是一个带权有向图,把图中顶点集合V分成两组,第一组为已求出最短路径的顶点集合(用S表示,初始时S中只有一个源点,以后每求得一条最短路径 , 就将加入到集合S中,直到全部顶点都加入到S中,算法就结束了),第二组为其余未确定最短路径的顶点集合(用U表示),按最短路径长度的递增次序依次把第二组的顶点加入S中。在加入的过程中,总保持从源点v到S中各顶点的最短路径长度不大于从源点v到U中任何顶点的最短路径长度。此外,每个顶点对应一个距离,S中的顶点的距离就是从v到此顶点的最短路径长度,U中的顶点的距离,是从v到此顶点只包括S中的顶点为中间顶点的当前最短路径长度。
(2)算法步骤:

a.初始时,S只包含源点,即S={v},v的距离为0。U包含除v外的其他顶点,即:U={其余顶点},若v与U中顶点u有边,则<u,v>正常有权值,若u不是v的出边邻接点,则<u,v>权值为∞。

b.从U中选取一个距离v最小的顶点k,把k,加入S中(该选定的距离就是v到k的最短路径长度)。

c.以k为新考虑的中间点,修改U中各顶点的距离;若从源点v到顶点u的距离(经过顶点k)比原来距离(不经过顶点k)短,则修改顶点u的距离值,修改后的距离值的顶点k的距离加上边上的权。

d.重复步骤b和c直到所有顶点都包含在S中。
引用自最短路径—Dijkstra算法和Floyd算法

我的解释

其实没有这么难,对于我来说,只有这几步:
找出最快能到达的节点。
更新它邻居的开销。
重复,再重复。
直到没有未处理的节点。
感觉被世界上最恶毒的小编耍了
别走!后面有料!

没有高铁的春运难题

一个人,去一个农家乐旅游,想要回到家乡长春,应该怎么回去?
那个人画了这张图:


真是一个简洁的图表
图上 意思 它是什么?
数字 时间 权重
城市 节点
箭头 方向 边(有向)

转换为dict

graph = {
    'start.': {'Beijing': 5, 'TrainStation': 0, },
    'Beijing': {'ShanHaiGuan': 15, 'ShenYang': 20, },
    'ShanHaiGuan': {'ChangChun': 20, },
    'TrainStation': {'ShanHaiGuan': 30, 'ShenYang': 35, },
    'ShenYang': {'ChangChun': 10, },
    'ChangChun': None,
    }

用来存储父节点和花销的散列表类似于这样:

costs = {
    'Beijing': 5,
    'ShanHaiGuan': float('inf'),
    'TrainStation': 0,
    'ShenYang': float('inf'),
    'ChangChun': float('inf'),
    }
 
parents = {
    'Beijing': 'start.',
    'ShanHaiGuan': None,
    'TrainStation': 'start.',
    'ShenYang': None,
    'ChangChun': None,
    }

这只是为了方便让您看懂。costsparents散列表(dict)无需手动实现,下面会告诉您如何自动根据graph生成对应的初始化的costsparents

Let's GO!

算法实现:

def find_quickest_way(graph, start, finish):
    # 根据图生成花销表
    costs = {}
    for k, v in graph.items():
        using_parents = graph[start]
        costs.update(using_parents)
        if k != start:
            if k not in using_parents.keys():
                costs[k] = float('inf')

    # 生成初始父节点表
    parents = {}
    for k, v in costs.items():
        if v == float('inf'):
            parents[k] = None
        else:
            parents[k] = start

    # 用来存储处理过的节点
    processed = []

    # 最近的节点
    node = find_nearest_station(costs, processed)

    # 开始狄克斯特拉算法
    while node is not None:
        # 如果最快的点是终点,则表明算法结束了
        if node == finish:
            break
        # 通向这个节点的花销
        cost = costs[node]
        # 所有可以连接到的点
        neighbours = graph[node]
        for t, c in neighbours.items():
            # 新的花销
            new_cost = cost + c
            # 如果花销更小,使它的这个邻居成为子节点
            if new_cost < costs[t]:
                costs[t] = new_cost
                parents[t] = node
            # 处理过了
            processed.append(node)
        # 最近的节点
        node = find_nearest_station(costs, processed)

    # 返回子父节点表
    return parents


def find_nearest_station(costs, processed):
    """傻瓜算法, 找到最快速的节点"""
    lowest_cost = float('inf')
    lowest_node = None
    for k in costs.keys():
        if costs[k] < lowest_cost and k not in processed:
            lowest_cost = costs[k]
            lowest_node = k
    return lowest_node

测试一下!

line = ['ChangChun']
# graph散列表见上文“没有高铁的春运难题:转换为dict”
my_parents = find_quickest_way(graph, 'start.', 'ChangChun')

while True:
    parent = my_parents[line[0]]
    line.insert(0, parent)
    if parent == 'start.':
        break

print(*line, sep=' => ')
start. => Beijing => ShenYang => ChangChun

Process finished with exit code 0

成功!

还记得最短路径—Dijkstra算法和Floyd算法这个文章吗?在开头提到过。这里面还有一个很好用的算法Floyd算法。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容

  • 1736年,瑞士数学家Euler(欧拉)在他的一篇论文中讨论了格尼斯七桥问题,由此诞生了一个全新的数学分支——图论...
    不困于情阅读 4,377评论 0 9
  • 1)这本书为什么值得看: Python语言描述,如果学的Python用这本书学数据结构更合适 2016年出版,内容...
    孙怀阔阅读 12,435评论 0 15
  • 1. 图的定义和基本术语 线性结构中,元素仅有线性关系,每个元素只有一个直接前驱和直接后继;树形结构中,数据元素(...
    yinxmm阅读 5,427评论 0 3
  • 姓名:龚珊珊 公司:宁波大发化纤有限公司 《六项精进》301期感谢组学员 【日精进打卡第21天】 【知~学习】 《...
    Miss曲奇阅读 86评论 0 0
  • 物理学的偏微分方程式通常用空间坐标系表示,坐标轴固定在空间中,或者在材料坐标系中,固定在材料的参考结构中,并在材料...
    Lpz95阅读 4,567评论 0 0