数据结构篇十九:图的最短路径

图的最短路径

  • 迪杰斯特拉算法
  • 贝尔曼-福特算法
  • 弗洛伊德算法
  • SPFA算法(中国西南交通大学段凡丁发明)

最短路径问题分为两类,一大类是求一个顶点到其余各顶点的最短路径问题,另一大类是求各个顶点间最短路径问题。

迪杰斯特拉

迪杰斯特拉算法就是求解一个点到其余各点的最短路径算法,无向图带权图和有向带权图都适用。缺点是不适用权值为负数的图(后面会讲解原因)

算法步骤

  1. 初始的点为起点,我们用s集合存储已经确定最短路径的点的集合,那么s={v},起点加入。其余各个点到v点的权值存储在dis数组里,不是直接连接的点距离都是无穷大
  2. 从dis数组选出一个顶点u,这个点u到v点距离最小,把u加入s集合表示u已经确定了最短路径
  3. 以点u为中介点,将除了s集合存储的点以外的其余点逐个判断,如果某个点x存在dis[u]+u点到x点距离<dis[x],就更新x的路径。
  4. 重复2,3步骤,直到s集合包含了所有点。

我们还是直接上图看完整流程

在这里插入图片描述

首先我们先准备几个辅助数组,我们假设从点A为起点,找其它点到点A的最短路径

节点 A B C D E
下标 0 1 2 3 4
权重 0 4 2
标记 1 0 0 0 0
前驱 -1 0 -1 0 -1

我来说明下,这几个数组的作用
权重数组存储每个点到A点的最短距离

前驱数组存储的是每个点前驱点下标,例如B点前驱是0,表示B和A连接,前驱是A

标记数组存储的是当前点是否已经找到了最短路径。

接下来我们准备工作做好了,开始干活了!

1.按照算法步骤,找出没被标记点中权重最小的点,我们找到了D点,将D点标记为1,表示D点以确认最短路径,然后以D点为中介判断未标记点,首先来到了B点,权重数组中B对应的是4,根据算法步骤3,我们计算出权重数组D+BD距离2+1=3 < 4(4就是权重数组B的值)所以B当前有一条路径比之前近,所以修改了B点对应的权重为3,同时更新它的前驱是D的下标。意思就是经过D点到B,更加近。同理继续看下一个未被标记的点C,继续计算权重数组D+CD距离 2+1=3 <∞,拿C点也要修改权重为3,同时更新C点前驱是D,继续看下一个未被标记点E,发现权重数组D+DE=9<∞,所以也修改E点权重为9,同步更新它的前驱是D。如下表就是第一次更新后的结果

节点 A B C D E
下标 0 1 2 3 4
权重 0 3 3 2 9
标记 1 0 0 1 0
前驱 -1 3 3 0 3

2.找出当前表中未标记点权重最小的,来到了B点和C点,我们选择B(随便哪一个都行)将B标记为1,接着逐个判断未被标记点,首先是C,权重数组B+BC距离 3+4 >3所以不修改。又来到了E,权重数组B+BE 3+∞ >9 ,也不修改,如下表就是第二次更新的结果

节点 A B C D E
下标 0 1 2 3 4
权重 0 3 3 2 9
标记 1 1 0 1 0
前驱 -1 3 3 0 3

3.找出当前表中未被标价点权重最小的是C点,将C点标记为1,然后判断未被标记的,只剩E点,权重数组C+CE距离 3+3<9 所以修改E点权重是6,更行E点前驱是C的下标,如下表就是第三次更新的结果

节点 A B C D E
下标 0 1 2 3 4
权重 0 3 3 2 6
标记 1 1 1 1 0
前驱 -1 3 3 0 2

4.找出最小,只剩下E点,直接标记E点是1,结束。

节点 A B C D E
下标 0 1 2 3 4
权重 0 3 3 2 6
标记 1 1 1 1 1
前驱 -1 3 3 0 2

有了上面一张表,我们就可以求出每个点到A点的最短路径了,我举两个点例子。

首先是点B,根据前驱下标进行寻找,B前驱下标是3,对应点D,所以B点前驱是D,接着D点前驱下标是0,对应点A,接着A点前驱下标是-1,退出。所以整个逆序路径就是B-D-A

接着看E点,前驱下标是2就是C点,C点前驱是3是D点,D点前驱下标是0,是A点,A点前驱是-1,退出,整个逆序路径是E-C-D-A

//迪杰斯特拉算法
void Dijkstra(struct MGraph *g, char obj)
{
	int *temp, *dis, *pre,index,min,k;
	temp = (int*)malloc(sizeof(int) * g->numVretexes);
	dis = (in
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值