图的最短路径(一级)

下面我们来讲图里面的最后一个内容,最短路径,我们已经有一个初步的认识,比如我在高德地图里面驾车,给我多条路径,实际上

这三条路径都是最短路径,他们都是最短路径,只不过是按照不同的标准,不同标准比出的路径,不见得是具体最短,也可能是拥堵

最少,或者红绿灯最少,那他怎么知道红绿灯最少呢,他怎么知道拥堵最少呢,他怎么知道距离最短呢,就是靠各条边的权值,就靠

权值的,比如两个点之间有一个权值代表距离,就好比,我要从a到e,如果3代表距离的话,我要找距离最短的,如果3代表拥堵程度

的话,我要找拥堵值最少的,这是一个,我们来解决这个问题,最短路径,在很多应用里面,带权图这个值是有作用的,用来描述整个

网络的,比如通信网络,交通网络,交通网络可以代表距离,可以代表红绿灯,可以代表拥堵程度,这种情况下,各边的权重就对应于

两点之间的通信的成本或交通的费用,这个时候,就有一个典型的问题就是,在任何的两点之间如果存在通路,那么最少的消耗是

什么,这是一点,这是一点,他们中间其实还有很多点,他们中间还有很多点的,他们并没有直接相连,就好比一个是a,一个是e,

他不是直接相连的,他们是通过其他节点串联起来的,而连起来的,是这么来的,最短路径,我们要求他们之间最少的消耗是多少,

那在我们的图里面,数据结构里面,我们用一个专门的名词来解决这个问题,叫最短路径,这是一个网络,比如交通网,并且这个

有方向的,有方向的什么意思,v1能到v2,v2就不能到v1,就不能到这儿,大家要记住,我们的目的是要从v1到v8,我要从v1到v8,

你看这个路径可多了去了,我想找里面的最短路径,最短路径里面有两类,有人说我直接走,一个5,一个2,这里一个9,如果这个

权代表时间的话,你这么看着直接走,你花的时间很多的,你花的时间很多,你要是换一个来说,你有时候发现走了好几条边,

那可能还少呢,3,1,1三条边权值加起来才是5,所以这一块,从v1到v8,最短路径是什么,有人说我一眼能看出来,你能看出来吗

估计够呛吧,北京的交通地铁图放在这儿,你能看出来吗,看不出来,是不是要靠算法去算,靠计算机来计算,写完代码要计算,

是这么来做的,我们把最短路径分为两大类来讨论
第一类跟权值无关的,段数最少的最短路径,生活案例就是换乘最少,最好是能这么来,这边一上一个公交,一直把我拉到这儿来

这是一个站,这是一个站,中间不用换乘,哪怕饶了非常远,我也愿意,为什么,因为我的行李比较多,因为我还有这个需求,

因为我的路不熟,我第一次来北京,我就想一上公交,就直接把我拉到目的地了,有这个需求吗,是有的,换乘最少,我这个时候和

你的时间,和你的拥堵有没有关系,没有关系,换乘最少就好,那这个怎么办啊,跟上面的权值有没有关系,没有关系,我就看怎么跳,

从v1到v3跳一次,v3到v6换一次,v6到v8就到了,怎么经过的顶点少,就走哪一个,这是一类问题,这个跟权值无关,这个怎么来解决呢,

只用广度优先搜索就可以了,注意我们这里写的是广度优先搜索,没有写广度优先遍历,还是有点差别的,基本道理是一样的,

它相当于我们这个广度优先遍历在这里的一个应用,这是一个


还有一个,权值最少,可能是时间最少,也可能是距离最短,到底是时间最少还是距离最短呢,那就要看这个权值代表什么含义了,

如果你这权值代表距离,那我就要找代表距离最短的,如果你的权值代表时间,我就要找时间最少的,知道我们在说什么吧,然后我们就

开始做了,看这一个
第一个问题特别简单,段数最少,换乘最少的,还是就相当于树的遍历,需要借助队列来实现,怎么来办呢,我们大家画一下,跟我们刚才

讲的广度优先遍历差不多,先画一个队列,队列在这儿,先把谁放进去,比如我们v1就不放了,因为我们是从v1出发的,我们要的是段数最少

我们来处理或者来看的话,我们就得从第一个开始看,你不能想当然的想一个,这样不保险,大家不要想换乘最少,就快速的得到一个结果

不可能的,还是的从第一个,第二个,他还是要经过一系列的比较来实现的,那请问我们的v1要到哪些顶点,与v1之间的相连的换乘点,

有哪些,有v2,我们就直接写数了,v3,还有谁啊,还有v4,如果我到这三个顶点的话,相当于我直接到了,直接到就可以了,但是你要好好看,

234里面是不是8,不是,你先找到与v1相连的连接点,看到他们是不是v8啊,不是,不是怎么办,不是我们就得找,2你是我的目的地吗,不是

那如果从你这里出发,一步直接到是不可能了,最好是换乘一次了,那好,与v2直接相连的有谁,有v5,有v6,是不是还有v3,那这个时候

我们怎么办,比如我们写一个3,有人说我们这个3到底写不写,就看算法里面怎么实现了,反正这个3要标记一下,就已经访问过的,

我们要做一下相关标记的,这个明确一下,比如我们3先写到这里吧,先2已经出去了,2肯定是已经访问过了,2是到不了的,与2相连的3

还有多少5,6,到这儿,然后我们再看这个3,3能不能直接到啊,3是不是我的目的地啊,不是我们的目的地,与3直接相邻的有谁,有6,有4,

还有没有,没有了吧,4是不是我们的目的地啊,不是,那如果我们通过4到的话,6和7,如果我们能够到这3个顶点的话,可以直接到了,

那现在我们是到不了的,因为234都不是我们的8,那下面的顶点里面,如果包括我们的目的地,相当于换乘一次就够了,那我们来看呗

3就已经不考虑了,你之前已经访问过3了,5是不是我们的目的地啊,5不是8,那就5出去,5出去之前要做一件事,5可以到谁,5能到6吗

5到不了,是不是到不了,5能到8,这儿写一个8就可以了,这儿写一个8,然后我们再来看,5出去了,6不是我们的目的地,但是6可以到7,

到8,6可以到7也可以到8,我们在画这个队列了,这个6已经不处理了,因为已经处理过了,4处理过了,6处理过了,7可以到谁啊,

7可以到8,如果你在这一段里面包括我们的目的地的话,相当于中间换乘一次,第二次就直接到了,但是这里面有没有啊,

这里面没有,那我们再往下看,8是我们的目的地吗,那我们就可以达到了,换乘两次就可以到,如果我们把问题变一下,我要从v1出发,

我要到v9,v9会怎么样,这里面有没有v9,没有v9,你怎么知道没有v9了,就是把我们队列里所有的元素都走一遍,走到最后,

队列成了空了,也没有找到v9,那就不存在了,这就是关于段数最短的一端路径,可按照这种方式来实现,看来这就是一个简单的思路

我们现在知道到8了,你怎么知道是跳了两次呢,那跳了两次,哪一块路径 是两次啊,你看这是一条路径,还有别的吗,别的还有没有,

这是不是两次,这是不是两次,你还要记住这条路径是哪条路径,比如我换成3次,那还要知道具体走的是哪一个顶点,根据算法的

进一步的细节了,对于我们来说呢,我们要知道,我们要记住这样一个结论,什么结论,求最短路径,段数最少,跟权值无关,用什么来实现

用广度优先搜索来实现,广度优先搜索是怎么回事,跟我们之前的广度优先遍历很相似,需要借助队列来实现,先找与起点直接到达的

顶点,看直接打到的顶点是不是我们的目的地,如果不是的话,再找他的下一个换乘点,就可以了,就一步一步推,就好比一步一步的

扩散呗,怎么扩散啊,这是起点,这里面有没有,这是直接到的,没有,再找换乘的,换乘一次的,再找换乘两次的,换乘三次的,

看换乘几次,找最早能找到的8,最早找到的v8,肯定是我们换乘最少的,这是一个,这个内容我们就给大家说到这儿
那下面我们要看后面这个问题,这个问题就要稍微复杂一下了,但是也特别有意思,权值最小,我要的是时间最少和距离最短

看着我要从v1出发,我要借助这些权值,到v8,有一条路径,各个路径最后权值是最小的,那这个时候我该怎么办,我直接走呗,

直接过去,5+2+9,16,这是不是最小的,比如我先走2,在走3,或者我不说别的,v6到v8是不是9啊,但是我绕一下,先到7再到8,

是不是1+6啊,比直接走这个9是要小啊,那这个路径就可以排除了,关键是有众多的路径,大家想一下交通图,那个路径

不计其数啊,我怎么从里面找到最合适的,这么来写哦,这个人叫狄克斯特拉,人家专门研究这个问题,给出了一个解决方案,

所以这个算法的名字,是以人家的名字来命名了,中间要经过一系列的过程,过程就在这儿,他一直在重复一个操作,

不复杂,首先要明白他的起点是什么,所有的顶点有8个,起点是谁,v1,他的初始状态是这么来的,我先定义一个数组,

这个数组目前只有一个顶点,我的起点v1,还有一个数组T数组,他有谁啊,他有其他所有的顶点,然后呢我这里还维持着一张表,

一个表格,当前节点是除了起点之外,所有的顶点,因为我这里没有任何的计算,我目前暂且认为起点到这些顶点最短距离

都是-1,-1就认为无穷大,注意了,因为我还没有计算,所以我暂且认为v1到这些顶点的最少路径,目前都是无穷大,

我们用-1来表示,这是初始状态,我们经过一系列的运算之后,最终得到了一个结果,这个最终的结果是什么,

结果就是T数组里面的元素,一个也没有了,都到S数组里面了,S数组里面原始只有一个v1,但是我们经过各个步骤之后,

已经把T数组里面的值,依次的已经放到我们的S数组里面了,已经全了,但是你仔细看,他放的顺序不是随便放的,

是按照234的顺序来吗,不是吧,6,7,5,8,他是有一点依据的,一个一个放进去的,当我们把T数组的元素都放到S数组里面的时候

我们同时也得到了一张表,这个表就在这儿,我们又得出一个结论,从这个起点到v8,他的最短距离是多少啊,是12,

最短距离是12,我们不仅得到了v1到v8的最短距离是12,我们还得到了v1到其他各个顶点的距离,比如v1到v2,...v8的最短

距离分别是3,4,5,8,6,7,12,这个表是不是非常有用啊,是v1到各个节点的最短距离,我的成果有第一个,

知道v1出发,到网络中各个节点的最短距离,这个成果是很丰硕的,并且我还知道,我从v1出发,到v8这个路径是12,

那走的是那一条路径,就在这个表格里面存着呢,怎么存着呢,v8的前一个节点是谁,是v7,v6的前一个节点是v6,

v6的前一个节点是v3,v3的前一个节点是v2,v2的前一个节点是v1,大家记住了,回到这里来,看对不对,

这就是我们所说的最短路径,那我要想找v1到v5的最短距离呢,也在这个表里面,这个表里面都有,比如我想到v5

的最短距离,v1到v5的最短距离是8,从v5前一个是v6,v6的前一个是v3,v3的前一个是v2,v2的前一个是v1,

大家记住这么一个顺序了,我们到的是v5,12365,看是不是,我们讲到这想一下,就是一个表格包含的内容太多了

不仅有最短距离,而且包括最短的路径,下面我们就一步一步的来实现
我们来研究一下这个算法,我们要记住这个人的名字,使用狄克斯特拉,当然是英文单词翻译过来的,我们把这个

问题说明白,这里又一个专门的表格,就是刚才的内容,打起精神来,虽然是了解性的,但是你不觉得很有意思吗,

看这一块啊,我们开始回答这个问题了,初始状态是S数组,里面只有起点,T数组有其他所有的顶点,v1到其他顶点的距离,

暂且认为无穷大,下一步,我要找与v1直接相连的顶点,先找与v1直接相连的顶点,里面有谁,v2,v3,v4,距离是几,3,5,6,

v1是不是可以达到这三个顶点,3,5,6,v1到这三个顶点还是无穷大吗,不是的,更新这个表,怎么更新了,到v3,到v4的距离

是3,5,6,前一个顶点是谁,是从v1到达的这儿,这是我们的一个成果
下一步怎么办,我们要从这个距离里面找到一个最小的值,哪个值最小啊,你可不能说不一样,-1是无穷大的,是不是3最小

3最小怎么办,3代表谁啊,3代表v2,从下面这个数组里面把值最小的v2拿出来,放到这儿,这个图是哪个图啊,那下面我们要

干什么了,下面我们要从v2出发,看他可以到哪些顶点,v2可以直接到v3,可以直接到v5,可以直接到v6,距离分别是多少,

到v3是1,到v5是7,到v6是4,那大家想一想,这个v1到v2距离是不是3,那请问,我们这个v1到v3,v5,v6的距离,应该是多少啊,

我从v2到这三个的距离,是不是1,7,4,如果不是从v2出发,从v1出发,你这个距离是不是要加上一个3,再加上3,因为3是我们

所有路径最短的吗,从v1到v2的距离,3和1,7,4分别相加,这是4,这是10,这是7,我们就可以再改变一下了,本来v1到v5到v6

都是无穷大,现在变成多少了,现在变成10和7了,就是v1到v5到v6的距离,一个是10,一个是7,是不是要比无穷大小啊,

改一下,怎么改,这儿改成10,这儿改成7,上一个顶点是谁,v2,那是这么来的,明确一点,上个节点是v2,4要不要改啊

这个4要不要改,你看哦,4是什么意思,也就是我们从v1到v3,直接走这个路径是5,现在我又算了一下,我要走这个路径

居然是4,那怎么办,是不是要把这个路径替换一下,替换一下,把这儿改成4,还要改一个位置,我们到达v3的前一个顶点

可是通过v2定的,还是通过v1吗,不是的,我们这一步就做到这儿,在这个成果里面我们还要找一个最小的,之前的v2'

早已经加进来了,就是在v3和v8里面找最小的,现在是v3,那我们要做一件事,提出来怎么办,在这个图里面找,从v3出发,

可以直接到谁,可以直接到v4,从v3到v4的距离是1,还有谁到谁,到v6,这是2,可是你不要忘了,我们要从v1出发,最终

到达v3,是不是花的距离是4,花的权值是不是4,那我要拿这个4,跟这个1相加,是几啊,是5,拿着这个和2相加是6,

这什么意思啊,6是比这个7小啊,5是不是比这个6小啊,这说明什么,我们找到了一个更短的路径,当然我们的最短路径

是借助谁实现的,是借助这个v3来实现的,不再是通过v1,不再是通过v2了,我们要做一个操作,把这个值改成5,

把这个值改成6,还要再做一点,再改什么位置,到达v4和v6的前一个顶点是通过谁啊,是通过v3吗,把v1和v2改了,

直接改成v3,改他就可以了,告诉我,下面就是完全重复了,我们又得到这个结果,告诉我们该干什么,下边我们要

干什么,这个v2,v3已经进到上面这个数组里面了,剩的是不是45678,找一个权值最小的,是5,权重是5,节点是v4,

把这个v4放进来,放进来之后要干什么,以v4为顶点,他直接相邻的顶点有谁,有v6,v7,分别是几,3和5,

一个3一个5,v1到v4的最短距离是几,是5,3加5是几啊,8,5+5是几啊,10,下边我们要干什么,8和6比8要大,你这个不是

最短路径,但是这个10呢,到7的话,之前还是无穷远啊,现在是10,这要变一下,怎么改,这个6是不变的,这个-1要变成10

还要变一下,怎么达到这个v7的,他的前一个顶点是v4,我们又得到了这么一个结果
再往下看,我们要在5678里面找到一个节点,找到一个值最小,是不是6啊,那我们就要做一件事了,把这个v6加到里面

我们就把它讲完吧,怎么办,以v6为顶点,他可以直接到谁,直接到v5,直接到v7,直接到v8的,并且到v5是2,到v7是1,

到v8是9,然后干什么呢,v6进去了,v1到v6的最短距离是6,他是6的,6+2是几啊,8,6+1是7,6+9是15,拿着这个8和10相比,

我们又找到了一个最短路径,把这儿改成8,前一个点是v6,拿着7和10比,这要改成7,前一个顶点是通过v6来找的,

拿着15和无穷大比,这儿要改成15,我们又得到了一个结果,一步一步来的,这个时候T数组里面还剩几个,还剩3个,

一个v5,是8,一个v7是7,一个v8是15,8,7,15里面最小的是7,我们把7放进来,又出现了什么情况,7可以到谁,

7只能到8,权值是5,而我们要知道,从v1到v7,最短路径现在是7,7+5是几,12,拿着12和15相比较,12小于15,

又找到一条最短路径,前一个节点是谁,是v7l,又解决了,然后怎么办,然后我们在v7,v8里面,找一个小的值

一个是8,一个是12,把v5提上去,再来看,v5可以到v8,只是权值是6,而我们要知道他到v5的距离是8,

8+6是几,是14,14和12比,12还是最短的,不走你这个路径,再往下走,不用走了,因为这里面就剩下一个节点

就剩下一个v8了,v8就是我们的目的地,直接把v8加进来,最终我们就得到这样一个结果,这个结果告诉你什么,

从v1出发到v8的最短距离是12,这是第一个成果,其实这个值就是起点为1,到这些顶点的最小距离,都求出来了

如果你要是换一个顶点,从v2出发,你可以求出v2到其他顶点的最短距离,也是可以求获的,并且我们这里还可以

干什么,还可以知道怎么从v1出发,怎么到达v8的,就是前面这一列起作用了,v8的前一个是v7,v7的前一个是v6,

v6的前一个是v3,v3的前一个是v2,v2的前一个是起点v1,那关于最短路径就给大家说道这里了
再次总结,

最短路径在实际的应用中还是特别有用的,段数最少的与权值无关,直接用广度优先搜索就可以了,

需要借助队列,权值最小的,这里权值代表什么含义,不确定,可能是时间,也可能是距离,也可能是拥堵,

都有可能,狄克斯特拉算法,最终我们会得到这样的一个结果

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值