加质Q(`⌒´Q)⊂(˃̶͈̀ε ˂̶͈́ ⊂ )mua
各位同学大家好,本节课我们来学习图的第2个应用最短路径问题,什么是最短路径问题呢?我们先来看一个生活中的例子,那么在生活中现在有一个小镇,小镇上有若干个房子,我们每个房子之间可能会有这样一条路把它们联系到一起,这就是彼此可以相互达到,那么现在我们愿意一个房子为起点,另一个房子为终点,想修算一下,从起点到终点最短的那条路径是什么?那么根据我们之前学习过的广度优先搜索解决无全图的单元最短路径问题,我们可以去算这样一条最短路径,他是经历了一个房子,那么此时如果我们考虑路的长度,也就是每一条路每一条边增加了一个权重,此时如何计算最短路径呢?最短路径也就是边数最少的那条路径吗?答案是不是的,我们发现它的最短路径是不是这一条啊?呃,权重此时如何计算最短路径呢?自然路径就是边数最少的那条路径吗?答案是不是的,我们发现它的作用路径是不是只有一条啊,它今天的长度为期是最短的这样一条,我们发现它是不是经历了三条边,所以说加上权重之后,我们就无法通过广度优先搜索来解决单元最短路径问题了,那么在这样债权的图当中,我们是如何定义最短路径呢?权重之后我们就无法通过广度优先搜索来解决单元最短路径问题了,那么在这样债权的图当中,我们是如何定义最短路径的呢?也就是两个顶点之间带全路径长度最短的路径为最短路径,其中在全路径长度表示为在带全图当中,把从一个顶点为等边一个顶点u所经历边的全是之和称为路径的带全路径,长度与我们刚刚描述的是一致的,那么知道什么是最短路径好,那我们本节课我们就来学习一下,如何在带全图当中计算最短路径,那么第1种方法则是理解斯特拉方法,第2种方法是弗洛伊德方法,我们首先来学习理解斯塔拉方法好,接下来我们再学习一下,理解斯塔拉算法,它是计算债权主单元最短路径算法,这里是从一个顶点为原点到其他各个顶点的这个楼叫三。它是计算带全图单元最短的算法,这里是从一个顶点为原点到其他各个顶点的这个楼叫好,我们来看怎样实现一些司法,然后我们给用了三个数组,我们先来看一下这三个辅助数组都是代表什么样的含义乌,首先第1个辅助数组是较为s的这个数组,它表示的是我们已经计算完成的顶点的顶点集,也就是我们标记了已经计算完成矩阵模型的哪些景点,因为我们在实现这些SARS算法的时候,每一个定点的作用就是我们是逐步计算完成的,所以我们要把这些应用计算完成的标记一下,那么这样一个速度怎样,初始数字怎样初始化呢?来看一下初始化时是吧?各个顶点对应下它的值都初始化为0唯一也就是老。1也就是我们把圆点加入到已经计算完成零点的这个集合当中,那么这里我们用0表示了,他为计算完成而用一表示让他已经算完成好,这就是第1个辅数组s了,第2个辅助数组是distance的缩写,dst它表示的就是最短路径的长度什么样最短路径的长度呢?是记录从原点为圆弧到其他各个顶点当前的最短路径长度,那么我们用数字下标表示另一个端点的小的编号,而大家要注意点是这也是当前的最大长度,也就是说这样一个数组是不断更新的,我们在训练的过程当中是不断更新这样一个数组的,那么它是如何初始化的呢?数组中的值初始化为原点到各个顶点边的全值,也就是说第4套数组它a下标的值,我们把它复制为数字。中的值初始化为原点到各个顶点边的全值,也就是说disc数组它a下面的值,我们把它复制为边的那一个二位数组0a下面下的是那么这里,因为我们的原点是v,零它的下标是0,所以我们赋指的是银行的值,那么根据我们原点的改变,那么对应的航标也可能会发生改变,大家要在实际的使用当中注意一下这个问题,好这就是第2个数数,所以我们来看第3个数数字和pass,它是计算了什么呢?它是保存了我们这一条最短路径经历的顶点序变,那么怎样用这样一个一位数组保存原点到剩下的所有顶点经历的最短路径的顶点序列呢?我们来看一下它是如何实现的进入从最短路径中顶点的前学节点每一个我们是。顶点的前驱节点也就是每一个开始数组下标时计算的是该顶点的前需顶点,我们是从哪一个顶点到达该顶点到 GPSI保存的是为a到vI最短路径上vI的前驱节点,那么最后我们利用不断的求前序节点,就可以计算v到vI的这一条就能静了,那么接下来我们就来看它的初始化,这样一个数组初始化时,我们要若圆点v0到该顶点vI有一条有相边或者是五相边则愿派3为0,否则用派3为负1,因为我们在初始时,是不是把这次的数组中每一个对应下的20都计算为原点到对应相邻节点,它这样一条与上面的长度啊其实我们最开始时相应的这个零件就是你就试着用吧不知为对应。上一节点她这样一条有下面的长度啊,所以其实我们最开始时与原点相应的这个零点他的钱去景点就是我们的原点,也就是这里的v0,所以我们把它复制为对应v0的数据下标好,这就是fa的初始化好,这就是三个辅助数组以及他们的初始化好,接下来我们要学习哪些四大算法的具体算法执行的过程,从这样一个算法的实现,其实与我们之前提到过的算法非常的相似,但新法的策略,首先你就是啊初始化数组,按照我们之前提到过的初始化方法,说实话三个辅助数组,那么这里为了后续的说明方便,我们引用了一个几个s,其实这个几个s的意思用我们s的那个辅助数字是相同的,它保存了所有我们已经求得的已经计算完成的哪些顶点加入。到已经计算完成的那些顶点,那么首先我们所有将原点加入到代几个当中,我们利用原点为v0,所以我们要将0加入到s结合当中好,这就是第1步初始化,接着第2步就是计算的过程,计算从顶点集合v减s中选出一个顶点为j,什么意思呢?也就是从所有还没有计算完成最短路径的那些零点当中选出一个顶点vg,这样一个顶点还需要满足条件满足什么条件呢?就是后面所叙述的,它要满足它是原点,到剩下的这些零点当中路径长度最短的那一个顶点,也就是我们之后表达式所表达的意思,那么找出这样一个满足该条件的顶点,然后将该点点的下标加入到我们的集合s当中,其实也就是将辅助下标s下的值赋值为一表示第三部第三。先要计算它了好,这就是第2步,其实我们来看第3步,第3步就是我们加入了这个顶点之后,是不是要对这次的数组进行修改了,所以我们要修改此时从v0出发到集合未见s上任意顶点为k的最短路径长度,因为我们引入了一个新的顶点为j,那么因为vj到我们剩下的各个顶点上会存在边这个因为存在着这些边,所以它可能最大的问题差不多会发生改变,它可能会更小,那么也就是若到vj这样一个顶点的最短路径,长度加上垂直到另一个顶点,vk的这样一条边,要小于原先我们保存到z次数当中的长度时,我们则要对它进行修改,当更小的复制给sk,然后同样我们要修改对应保存路径的这个辅助变量,辅助数组态色魔,此时顶点vk是不是通过vc到vk这样一条有线边打到的呀是要交。对应我们保存路径的这一个辅助变量,辅助数组派此此时顶点维k,是不是通过维j到维k这样一条两相边达到的呀?所以要将数字下标为k的这样一个值负值为g表示。路径的这一个辅助变量辅助数总pass此时顶点为k,是不是通过vj到vk这样一条有线边打造的呀?所以要将数字下标为k的,这样一个值负值为g表示从 v之一到达的vk好,这就是第3步,我们来看看小例子来理解一下这样的第3步,那么首先我们有一个v0,一个起始点起始景点,起始景点经历了若干经典到达了我们的vk,这样一个零点,我这个用虚线表示,那么则表示这不是一条边,这是一个路径,那么在其中经历了若干个顶点,那么它的长度是不是就是我们现在保存的这个boss的培养,然后我们将vj又加入到了我们已经计算完成的这个顶点集当中,s当中此时我们又有了到vc的这样一个这个路径,它是ac的j从未。想变,那么它的长度是什么呢?它的长度则是对腰我们保存在零件矩阵当中的量,也就是啊x啊,gk下表下大值,那么我们在第3步所做出的判断,是不是就是判断d4k这样一条路径和d4j1加上r4j1,这样一条路径哪一个长度更短啊?我们要向d4k更新为更短的那一个值,这就是第3步的作用,那么接下来我们只要重复二三步操作能减一次,为什么有能减一次啊?因为除了原点是不是还剩n减1和顶点啊?直到x轴不好,全部顶点我们计算完成了原点到所有剩下的顶点的最短路径长度,然后这就是解决斯特拉的算法描述,可能光描述而算法大家还是不太理解,有些细节不太清楚,接下来我们就来举个例子,这是一个。实现怎样实现该代码,其实实现方法用之前描述的算法过程是一致的,首先它的名字叫吉杰斯特拉,承诺参数有两个,第1个是这一个搜寻的图片,第2个是我们的原点的编号,v首先第1步是不是还是初始化呀?这个代码就是初始化代码,那么我们首先初始化了三个辅助的数组,ss和disc,那么它的速度大小为顶点的节点数量,然后我们实行了一个放循环,它则是对这三个辅助速度进行初始化的步骤,怎样初始化呢?依旧是按照我们之前所叙述的初始化过程,我们将disc复制为对应好的所有的边,也就是对应所有边大的全值,然后sa我们要把它都复制为0,也就是s的这个辅助所都全赋值为0小云。代表的是无穷大,我们在语言编写当中可以先用麦克斯生命为它是一个非常大的整数,因为这个整数表示无穷大,那么如果它小于无穷大时则代表它存在这样一条有相变墨,所以就把它路径的前驱节点负责我们的这个起始端点v,然后如果它是无穷大的话,则说明从原点到这样一个顶点是没有有向边的,所以把它初始化为负1,它没有任何大的前去节点,接下来的两个语句,sv赋值为e所代表的是我们初始化了这个原点,将原点的下标赋值为e,并把pass下标下的值赋值为-1,为什么把原点判断下,标下的值要单独计算为-1呢?因为我们知道在连接矩阵当中,行标和列标相同的这个位置的值,我们要存放为0特殊的三四三。粗放为-1,接下来我们剩下的是不是只有2343个步骤了,那么第1个负循环实现的则是第4个步骤,也就是我们重复计算23的这个过程,首先这一部分是第2个步骤,第2个步骤大家还记得是什么吗?是挑选符合条件的第1次数组下标下最小的那个值,我们首先初始化了两个变量,两个辅助变量,第1个未变量,我们把它初始化为最大值,这个最大值是我们体现生命好的是当前整形变量,我们看到最大的那个数,它的作用就是帮助我们来挑选最小的那一个值,还有第2个属于变量u,那么接下来就是一个循环语句,我们就是电力这个数组变电机的数组,找到那个最小的值,他的条件是什么呢?判断条件要满足两个满足哪两个呢?第1个则是该顶点已经是在剩下的顶点期当中,也就是在那些没有计算完。一定是在剩下的零点几当中,也就是在那些没有计算完最短路径的面积当中,那么我们判断方法则是sj是否等于00表示为它没被选入,然后还要满足一个条件,就是它要比我们当前的这个面保存所有,只要小不断的修改,我们更小的这个值,那么这个我们就是找寻数字当中最小值的方法,然后如果。被选入然后还要满足一个条件,就是它要比我们当前的这个面保存缩小值,要小不断的修改,我们更小的这个值,那么这个我们就是找寻数字当中最小值的方法,然后如果它更小的话,则要修改两个变量,也就是我们刚刚提到过的那两个辅助变量面要向它修改为新的这个最小的值,u要向它保存为最小值的这个顶点的下标,然后这就是一个for循环语句找寻符合条件的最小值,然后我们要把对应u也就是对应我们刚刚找过的那个最小值的数字下标,将它加入到已经完成的集合当中,这就是52条的代码实现,接下来就是步骤,3不是3是什么呢?或者3是我们要修改对应的辅助数组,因为我们新加入了一个顶点,那么新加入的顶点会带来很多边带来很多变的同时就会营销。第1次数组最小值数组产生影响,那么我们想要对它们进行修改,首先我们还是放循环语句循环的,对于数字当中每一个顶点进行判断,那么判断条件你就有两个依旧还要满足它是未被标记的,然后满足的则是我们之前提到过的那一个判断表达式,那么如果它要小的话,则把数组当中的值进行更新,更新回来最小的那一个,那么对应pass数组下的指令需要更新,因为我们通过了一个新的顶点,到达了我们对应的这个顶点,那么新的顶点的数组下标,就是我们之前加入的那一个顶点的编号,也就是我们保存的这个u好,这就是第3个步骤,接下来我们只要循环23这个步骤,就可以实现我们的第1次纳拉算法是多少呢我们在这里看到了一个几点数量极大所以他,那么接近斯卡拉,它的算法时间复杂度是多少呢?我们在这里看到了一个二重循环,循环次数都是几点,数量的数量极大,所以它的时间复杂度为大,o为方。斯特拉它的算法时间复杂度是多少呢?我们在这里看到了一个二重循环,循环次数都是几点,数量的数量极大,所以它的时间复杂度为大,o为方是就是李杰斯,他算法的时间复杂度好,那么接下来我们来看一下这些四大算法它适用于所有的有相同吗?我们来看这样一个例子,我对该图做一个小的修改,把从1~2这条小墙边从一个正值修改为了一个负值,也就是说在该图当中存在带有负全值的变,那么我们来看一下这样的偶像图是否可以运用以及斯特拉算法来计算单元最短的叫,首先还是执行这些4套算法的这个过程,辅助数组以及初始化依旧从0.0作为原点进行实现之前提到的都是一样的也没有作出修改然后直行到第二轮时我们发现我们选了。然后执行到第2轮时,我们发现我们是不是挑选了顶点一样,因为顶点一对应它的路径差不多最短,切它也没有被标记,然后挑选0.1之后,你就要把它加入到标记的这个集合当中,然后要修改disc大数下面下的值,我们加入了0.1之后是不是引入了从1~2和从1~3这两条就相变了,那么我们来看到达顶点2的整个意思,我们以前保存的这个纸是3,它是从0~2这样一条有向边,这样一条有效的路径它的权重为3,然后我们因为加入了0.1,是不是还存在另外一条路径可以到达天天2啊,也就是从0~1再到2,这样一条有效的路径直我们来看,如果按照我们之前的算法描述过程,我们在判断时一定判断的这些顶点都是从危险s也就是剩下的零点当中挑选顶点却比较的。一定看到的这些顶点都是从v减s,也就是剩下的零点当中挑选,零点去比较的,也就是对腰辅助数字s,那么我们发现是不是2向下的值为1啊,所以此时更新过后到达顶点2的作用路径依旧是3,但是我们发现加入1~2这样一条负全值偶像变时,从0~1再到2,它的全值大小是不是为2啊?他要比三更小,但是底下4323法并没有把它更新为2,所以我们要记住,底下四大算法并不适用于含有负全面的图,这就是底下斯特拉三法的一个曲线性,那么有没有什么样的算法可以以集结423法它的适用性更广呢?啊,这个弗洛伊德算法它是什么呢?它是计算各顶点之间的计算中心,也就是说弗洛伊德算法计算完成之后,我们可以将顶点之间的所有的算入叫都可以表示出来,那么我们来看一下它是如何实现的,它的算法思想是必推的产生一个ng的发生序列,那么这样的发生序列则保存了对应从某一个定点到达,另一个定点导致的叫那么行号,也就表示的是起始顶点列号表示的字是终止顶点,为什么是这样一个序列呢?这样一个结果矩阵,其实它与我们对应几个4313法是一样的,也是逐步上升的过程,从大f1>0一直到大an-1,那么这里大于负1代表的是我们初始化的这一个矩阵,因为因为我们有n个顶点,所以我们要逐步生成n个矩阵,那么这样一个矩阵表示的是什么含义呢?那上面这个小标又是什么样的含义呢?我们来看它的含义。因为因为我们有n个零点,所以我们要逐步生成n个矩阵,那么这样一个矩阵表示的是什么含义呢?它上面这个小标又是什么样的含义呢?我们来看它的含义。A象标是kag下标下的值代表是顶点为a到顶点为j的最短路径的长度,也就是起始端点为vI中式端点为为之打上一条有效路径直且该路径经过的顶点,编号大于k,也就是说如果上标是k的话,则为abc经历的这样一条路径,它经历顶点编号不会大于k,也就是从0~k-1,怎样从k减1这样一个矩阵到达ak这样一个矩阵呢?我们来看一下初始化时,我们将a这个上标为-1的矩阵初始化为我们图的这个临界矩阵,那么初始化之后,我们就开始地推我们来看我们是如何从k减1到达k的。那么初始化之后我们就开始底推,我们来看我们是如何从k减1到达k的,我们是这样来计算的,它下周下的每一个值进行这样一次修改,也就是计算一个最小值的过程,比如说我们来看aj下表下的值怎样修改呢,我们计算两个值的最小值,把最小的那一个复制为ak,第1个值是ak-1这个矩阵ag下面下的值,第2个我们所要比较的值是ak-1ak加上ak-1kj判断这样一个和和ac-1aj哪一个更小?把更小的复制为我们新生成矩阵对应下标ac下的值,就是说我们没有加入k零点来看一下它的作用容器和加入了k零点来看一下它的最小的像哪一个更小没有加入。这样的长度从a到g,第2个则是计算了加入了k零点之后,从a到j到最小路径的长度,我们来看一下我们是怎样计算加入k零点之后的这样一个最短路径的,那么第1个值是不是就是从其实零点到顶点k这样一条最短路径,然后加上呢,是从k顶点c到终日顶点c的这样一条最大值降,那么其实顶点到达k零点,k零点,再从k零点c从k零点到达终止,零点加起来,是不是就是从歧视零点到达终止顶点的这样一条最大的价值,但是我们是不是途径老kr,所以说我们就把k零点加入了进来,那么这样说依旧有点冲向我们来看这样一个例子,现在我们有一个起始0点vI,那么它可以通过一个路径到达vj,它是最短的假设,我们计算到了ak减1这个矩阵。到了这个ak顶点之后,是不是从vI到vk有一条路径,那么它的自然路径也就是ak-1ak,这样下标下的值接着上,我们又从vk到达vj,有这样一条最短路径,它的大小是不是就是ak减1kj这样下标下的值啊?这样我们就有两种方法到达了vj这个顶点,那么我们就要判断则是上述这个公式判断哪一个路径更小刚刚小的赋值给ak下标下的这个值,也就是我们加入k之后更新的这个矩阵,好,这就是我们地推的方法,其实这样一个算法,我们利用了算法分析课程当中的另一种方法,就是动态规划的方法,有兴趣的同学可以去了解一下考察首先是。就是把对应到我们存放身边的这个以及矩阵复制给我们这个新生成的变量,a这个变量矩阵,首先这个矩阵其实是没有图形任何顶点的,接下来的第1步,我们想要加入顶这个顶点,生成a顶那个矩阵,怎么样加入领车停电呢?是不是要对军人当中的每一个指标判断进行修改啊,那么我们就来判断一个尝试一下,看看它是如何进行判断的。其实判断过程就是我们刚刚描述的那个过程,我们来找一个母角,这条路径是不是表示的是从顶点2~达0.1的这样一条有效的路径,大家注意,这不是边,这是有效的路径,那么这里有一个相互作用表示正无穷所代表没有这样一条路径,然后怎样进行修改呢?首先我们是不是要把0.0加入进来啊?加入的方法是不是就是之前所叙述的那一个方法其实零点七十二点到底。它的代码实现非常简单,我们通过了一个三重循环,这就是它主要的实验代码,我们来看一下它的函数函数,首先我们声明了一个辅助一个结果的那个矩阵a,那么它的大小为乘n的就是节点数量的平方,然后我们通过了一个二重循环来初始化了这个a矩阵,也是将对应的连接矩阵的值复制给了这个矩阵,我们需要一个二重循环,然后接下来这个三重循环则是我们主要的算法实现的过程,那么第1种循环是不是循环测试,我们要把每个顶点第1次的加入进来了,那么加入进来之后,那么加入一个顶点之后,我们只要对训练当中每一个值进行修改,所以在第1个循环下面里边是不是一个二重循环啊这是每一个超这就是为什么需要三个条件就是我们。则是对剧本当中每一个只要进行修改的过程,这就是为什么我们需要三个循环,最终的这个判断条件判断的就是我们之前提到过的那个递推关系式,也就是判断我们新生成的这一条有效路径直,会不会比我们之前存放的从a到j的这一条的强度性更短,如果根本的话我们是要更新ac好,这就是判断条件以及执行过程,我们通过这样一个三重循环实现了弗洛伊德算法,那么其实在很多比试当中,大家更喜欢使用这样一个算法,为什么呢?因为我们发现他是不是非常好记呀,DJ斯特拉斯奥虽然它有针对性,但是它其实不太好记,那么复述一个算法,我们则需要一个三方循环就可以实现了,它的时间可能度自然而然是几点数量级的地方,因为我们有这样一个三床的循环,所以同学们可能会有结论,除了一个算法,一定要比迪斯科拉算法要更慢,它的效率要更低结果是不是。这样一个三中的算法,所以同学们可能会有结论,除了一个算法,一定要比第422算法要更慢,它的效率要更低,当然是不是的,我们发现它涉及到的结果是不是每一对顶点之间存在的最大估计啊,而这些2/4的算法只计算了一个顶点到剩下的所有顶点的最大值,如果在这些3l算法当中,我们想计算所有顶点时间的,虽然不行的话,我们也要加上一个循环循环,对每一个顶点计算到剩余顶点的算,我们就这样的话是不是一个算法和服了一个算法,它的时间复杂度其实是不是相似的好,这就是服了一个算法,那么在课程当中,其实我们对这两种算法它实现的步骤,也就是说我们给你一个有向图,给你一个五香图,让你根据不同的算法来写出它的生成步骤,而对代码的编写要求其实是非常小的,大家也可以酌情的去学习,酌情的去记忆。