[算法] Dijkstra算法(带权有向图 最短路径算法)
一、带权有向图

二、算法原理

1)由于我们的节点是从1-6,所以我们创建的列表或数组都是n+1的长度,index=0的部分不使用,循环范围为1-6(方便计算)。
2)循环之前,我们先初始化dis数组和mark数组:
dis数组中保存我们需要求的开始点(start),到其余所有点的最短路径。初始化的时候,只初始化到自己能够直接到的节点的距离,不能直接到的距离初始化为max_int(即sys.maxsize)。
mark保存节点的状态,如果已经被计算过,则状态为True,还未被计算过,则为False
3)开始循环,注意,我们只循环[1,n]的范围。index==0不纳入循环。
4)N==1时,找到所有Dis元素中,对应mark元素为False的元素。找出其中最小值为10,对应的index为3,也就是节点3。然后在weight数组中,找到3能直接到的节点(且对应mark也要为False),这里找到3能直接到4号节点,且权重为50。此时判断dis[3]+50<dis[4],如果成立,则使用dis[3]+50更新dis[4]。由于dis[4]等于max_int,所以dis[4]被更新为60。
5)N==2时,找到所有Dis元素中,对应mark元素为False的元素。找出其中最小值为30,对应节点5。然后在weight数组中,找到5能直接到的节点(且对应mark也要为False),为4号和6号节点,且权重为20和60。此时判断dis[5]+20<dis[4],结果成立,所以dis[4]更新为50。同理dis[6]被更新为90。
6)N==3时,找到所有Dis元素中,对应mark元素为False的元素。找出其中最小值为50,对应节点4。然后在weight数组中,找到4能直接到的节点(且对应mark也要为False),为6号节点,且权重为10。此时判断dis[4]+10<dis[6],结果成立,所以dis[6]更新为60。
7)N==4时,找到所有Dis元素中,对应mark元素为False的元素。找出其中最小值为60,对应节点6。然后在weight数组中,找到6能直接到的节点(且对应mark也要为False),结果找不到6能直接到的节点。
8)N==5时,找到所有Dis元素中,对应mark元素为False的元素。找出其中最小值为max_int,对应节点2。然后在weight数组中,找到2能直接到的节点(且对应mark也要为False),为3号节点,且权重为5。此时判断dis[4]+10<dis[6],结果不成立,不成立则不更新dis[3]。
9)N==6时,已经找到到对应mark为False的元素,直接break出循环。整个计算最短路径的过程结束。
10)可以看到N==6时得到Dis数组的结果是:[max_int,0,max_int,10,50,30,60]。除去index==0的元素,从1-6的元素,即是节点1到所有元素对应的距离(1到2的距离为max_int,说明没有路线)。
三、Python实现
import numpy as np
import sys def dijkstra(start, graph_struct, node):
"""
function:dijkstra
args:
start 要计算的起始点
graph_struct 带权有向图的结构
node 图中节点个数
return:
dis 元素为-1时,表示没有路径。其余为距离
"""
# n表示有N个点,m表示M条边,x表示求那个点到所有点的最短路径
n, m, x = node, len(graph_struct), start
max_int = sys.maxsize
weight = np.full([n + 1, n + 1], -1)
dis = np.full(n + 1, max_int)
# 初始化权重数组,自己到自己为0.其他为暂为-1
for i in range(1, n + 1):
weight[i][i] = 0 for i in graph_struct:
# 所有存在边的位置填上权重,没有关系的位置保持为-1,表示不可直接到达
weight[i[0]][i[1]] = i[2]
# 如果是与我们要求的x点相关的点,则也将x到i的权重填入dis列表中
if i[0] == x:
dis[i[1]] = i[2] # 程序走到这里,我们就有了权重数组 以及 dis数组(x到各个点的距离,如果没有边,则为max_int)
# dis : [max_int, 0, max_int, 10, max_int, 30, 100], dis[0]不纳入计算,为了方便,我们只考虑index>=1的部分 # 定义内部search函数,开始计算x到所有点的最短路径,最终更新到dis中
def search(x, dis, weight, n):
"""
function:search
args:
x 要求的点
dis 距离数组
weight 权重数组
n 节点的个数
return:dis
"""
mark = np.full(n + 1, False) # 创建一个mark数组,元素个数为n+1,[1,n]表示1-n点是否被当成最小值加过,已经加过为True,未被加过为False
mark[x] = True # 要求的点x,直接标记为加过
dis[x] = 0 # 自己到自己的距离为0
count = 1 # 当前已经加了几个点,当前只有x点,所以初始化为1 # 开始循环,当count<=n时,说明还有点未被加过
while count <= n:
locate = 0 # locate记录计算出来马上要被加的点
min = max_int # 用于求最小值时比较用
# 找到dis里面,还没有加过的位置(mark[idx]=False)里面数的最小值对应的index。
# dis : [9223372036854775807 0 9223372036854775807 10 9223372036854775807 30 100]
# mark : [False,True,False,False,False,False],从中找出10的index为 3
# 该for循环完毕后,min中的值就是最小值10
for i in range(1, n + 1):
if not mark[i] and dis[i] < min:
min = dis[i]
locate = i
# 如果locate为0,则说明所有点都被加完了,直接退出循环
if locate == 0: break
# 如果locate不为0,说明找到了需要加的点,先对其进行标记
mark[locate] = True
# 加一个点count增1
count += 1 # 从我们找到的需要加的点locate(例如3)开始,看weight数组中他到各个点的距离
for i in range(1, n + 1):
# 如果某个点已经被加过了,我们就不计算locate到这个点的距离了
# 如果locate到某个点的距离为-1,说明没有路,也不计算
# 条件3:x到locate的距离(dis[locate]) + locate到点i的距离(weight[locate][i]) < x到i的距离 才能更新
if not mark[i] and weight[locate][i] != -1 and (
dis[locate] + weight[locate][i] < dis[i]):
# 条件都满足,则计算,并更新dis中x-->i的距离
dis[i] = dis[locate] + weight[locate][i] return dis # 调用search开始计算x到各个点的距离,记录到dis数组中
dis = search(x, dis, weight, n) # 打印dis数组
for i in range(1, len(dis)):
if dis[i] == max_int:
dis[i] = -1
print("%s点到%s点 %s" % (x, i, "的最短路径为%s" % dis[i] if dis[i] != max_int else '没有路')) # 返回
return dis if __name__ == '__main__':
# 列举所有的边的权重,并写入weight列表
weight_init = [(1, 3, 10), (1, 5, 30), (1, 6, 100), (2, 3, 5), (3, 4, 50), (4, 6, 10), (5, 6, 60), (5, 4, 20)]
dis = dijkstra(1, weight_init, 6)
### Dijkstra算法原理还是比较简单的,但是使用代码实现的时候比较绕。需要多加复习,熟记于心。
[算法] Dijkstra算法(带权有向图 最短路径算法)的更多相关文章
- [C++]多源最短路径(带权有向图):【Floyd算法(动态规划法)】 VS n*Dijkstra算法(贪心算法)
1 Floyd算法 1.1 解决问题/提出背景 多源最短路径(带权有向图中,求每一对顶点之间的最短路径) 方案一:弗洛伊德(Floyd算法)算法 算法思想:动态规划法 时间复杂度:O(n^3) 形式上 ...
- 图之单源Dijkstra算法、带负权值最短路径算法
1.图类基本组成 存储在邻接表中的基本项 /** * Represents an edge in the graph * */ class Edge implements Comparable< ...
- HIT 2739 - The Chinese Postman Problem - [带权有向图上的中国邮路问题][最小费用最大流]
题目链接:http://acm.hit.edu.cn/hoj/problem/view?id=2739 Time limit : 1 sec Memory limit : 64 M A Chinese ...
- POJ3565带权匹配——km算法
题目:http://poj.org/problem?id=3565 神奇结论:当总边权最小时,任意两条边不相交! 转化为求二分图带权最小匹配. 可以用费用流做.但这里学一下km算法. https:// ...
- 带权二分图——KM算法hdu2255 poj3565
进阶指南的板子好像有点问题..交到hdu上会T 需要了解的一些概念: 交错树,顶标,修改量 #include<iostream> #include<stdio.h> #incl ...
- Dijkstra 单源最短路径算法
Dijkstra 算法是一种用于计算带权有向图中单源最短路径(SSSP:Single-Source Shortest Path)的算法,由计算机科学家 Edsger Dijkstra 于 1956 年 ...
- Bellman-Ford 单源最短路径算法
Bellman-Ford 算法是一种用于计算带权有向图中单源最短路径(SSSP:Single-Source Shortest Path)的算法.该算法由 Richard Bellman 和 Leste ...
- 图(最短路径算法————迪杰斯特拉算法和弗洛伊德算法).RP
文转:http://blog.csdn.net/zxq2574043697/article/details/9451887 一: 最短路径算法 1. 迪杰斯特拉算法 2. 弗洛伊德算法 二: 1. 迪 ...
- 有向网络(带权的有向图)的最短路径Dijkstra算法
什么是最短路径? 单源最短路径(所谓单源最短路径就是只指定一个顶点,最短路径是指其他顶点和这个顶点之间的路径的权值的最小值) 什么是最短路径问题? 给定一带权图,图中每条边的权值是非负的,代表着两顶点 ...
随机推荐
- Flask登录认证
login函数 @app.route('/login/', methods=['GET', 'POST']) def login(): if request.method == 'GET': retu ...
- ElasticSearch 倒排索引简析
内容概要 倒排索引是什么?为什么需要倒排索引? 倒排索引是怎么工作的? 1. 倒排索引是什么? 假设有一个交友网站,信息表如下: 美女1:"我要找在上海做 PHP 的哥哥." 需要 ...
- Linux内存管理解析(一) : 分段与分页机制
背景 : 在此文章里会从分页分段机制去解析Linux内存管理系统如何工作的,由于Linux内存管理过于复杂而本人能力有限.会尽量将自己总结归纳的部分写清晰. 从实模式到保护模式的寻址方式的不同 : 1 ...
- ubuntu文件操作mkdir cp mv rm ln
pwd:显示当前目录 date:显示当前日期 cal:显示日历 ls:列出目录内容 cd:改变当前工作目录 ‘.’:代表工作目录 ‘..’:代表工作目录父目录 进入当前目录的父目录:cd /home ...
- Stream排序Map集合
最近小编自己一个人在负责一个项目的后台开发,其中有一部分是统计相关的功能,所以需要一些排序或者分组的操作,之前这种操作小编觉得还是比较麻烦的,虽热有一些现成的工具类,但是工具类的写法也是比较复杂的,但 ...
- Redis(六):list/lpush/lrange/lpop 命令源码解析
上一篇讲了hash数据类型的相关实现方法,没有茅塞顿开也至少知道redis如何搞事情的了吧. 本篇咱们继续来看redis中的数据类型的实现: list 相关操作实现. 同样,我们以使用者的角度,开始理 ...
- Nito.AsyncEx 这个库
有一个非常聪明的小伙子 (我高度赞扬) 叫 Stephen Cleary ,他写了一个很棒的 Extension 集,共同参与开发的还有 Stephen Toub (他显然是经验丰富的),所以我充分信 ...
- NOI4.6 最小新整数——切山游戏
描述 给定一个十进制正整数n(0 < n < 1000000000),每个数位上数字均不为0.n的位数为m. 现在从m位中删除k位(0<k < m),求生成的新整数最小为多少? ...
- 1-3课 介绍虚拟化技术、在虚拟机中安装windows7
虚拟化技术 可以使我们在同一台计算机上运行多个操作系统 用于教学环境 用于测试环境 和硬件无关 可移植到其他电脑直接使用 Ptov技术 不支持VtoP 节省管理成本 节省硬件投资 不用买设备 省 ...
- 团队项目——Alpha发布2
一.作业描述 这个作业属于哪个课程 这个作业要求在哪里 团队名称 CTRL-IKun 这个作业的目标 在这个星期内完成团队项目α版本的第二次测试和发布,完善出错设置 二.成员列表 姓名 学号列表 廖志 ...