SPF算法
百度百科:SPF算法也被称为Dijkstra算法,这是因为最短路径优先算法SPF是由荷兰计算机科学家狄克斯特拉于1959年提出的。
SPF算法将每一个路由器作为根(ROOT)来计算其到每一个目的地路由器的距离,每一个路由器根据一个统一的数据库会计算出路由域的拓扑结构图,该结构图类似于一棵树,在SPF算法中,被称为最短路径树。SPF算法是OSPF、IS-IS路由协议计算最短路径的基础。
在OSPF路由协议中,最短路径树的树干长度,即OSPF路由器至每一个目的地路由器的距离,称为OSPF的Cost,其算法为:Cost = 100Mbps/链路带宽。
参考文章
SPF(Dijkstra)算法完美教程
ospf学习-----SPF最短路径算法
SPF案例
如图,V0~V8是9台路由器节点,节点之间的值是cost开销值的大小,我们以V0节点作为根,计算到其他节点的最短路径,也就是在V0看来去往其他节点最近的路径。
我们创建两个集合,分别是:
S集合:每求得一条最短路径 , 就将其节点加入到集合S中,直到全部顶点都加入到S时,算法就结束,初始时S中只有一个源点V0,且自己到自己的cost为0
U集合:其余未确定最短路径的顶点集合,初始时U中有除V0以外的所有节点,且从V0到其他所有节点的cost为无穷
第一次,我们先从V0开始发散,V0与V1、V2直连的cost值分别是1和5,与其他节点不直连所以cost设为无穷大,因为V0->V1的cost值在U集合中最小,所以将V1标红并加入到S集合当中
第二次,我们从V1开始发散,V1与V2、V3、V4直连的cost值分别是3、5、7,与其他节点不直连所以cost同样设为无穷大,因为V0->V1->V2的cost值4最小(且小于第一次发散的V0->V2的cost值5),所以将V2标红并加入到S集合当中
第三次,我们从V2开始发散,V2与V4、V5直连的cost值分别是1和7,与其他节点不直连所以cost同样设为无穷大,因为V0->V1->V2->V4的cost值5最小(且小于第二次发散的V0->V1->V4的cost值6),所以将V4标红并加入到S集合当中
第四次,我们从V4开始发散,V4与V3、V5、V6、V7直连的cost值分别是2、3、6、9,与其他节点不直连所以cost同样设为无穷大,因为V0->V1->V2->V4->V3的cost值7最小(且小于第二次发散的V0->V1->V3的cost值8),所以将V3标红并加入到S集合当中
第五次,我们从V3开始发散,V3与V6直连的cost值是3,与其他节点不直连所以cost同样设为无穷大,这里要注意一下,V0->V1->V2->V4->V5的cost值为8最小,所以这一步不移动V6,将V5标红并加入到S集合当中
第六次,我们从V5开始发散,因为V0->V1->V2->V4->V5->V7的cost值为13所以更新前往V7的cost值为13,但是U集合里前往V6的cost值10为最小,所以将V6标红并加入到S集合当中
第七次,我们从V6开始发散,V6与V7、V8直连的cost值分别是2、7,与其他节点不直连所以cost同样设为无穷大,因为V0->V1->V2->V4->V3->V6->V7的cost值12最小(且小于第六次发散的V0->V1->V2->V4->V5->V7的cost值13),所以将V7加入到S集合当中
第八次,我们从V7开始发散,因为V0->V1->V2->V4->V3->V6->V7->V8的cost值16最小(且小于第六次发散的V0->V1->V2->V4->V3->V6->V8的cost值17),所以将V8加入到S集合当中
最终形成的SPF路径
最终的SPF路径以及由V0节点到其他各个节点的cost值分别如下
Bellman-Ford算法
百度百科:贝尔曼-福特算法(Bellman-Ford)是由理查德·贝尔曼(Richard Bellman) 和 莱斯特·福特 创立的,求解单源最短路径问题的一种算法。它的原理是对图进行V-1次松弛操作,得到所有可能的最短路径。其优于迪科斯彻(Dijkstra)算法的方面是边的权值可以为负数、实现简单,缺点是时间复杂度过高,高达O(VE),V和E分别是节点和边的数量。但算法可以进行若干种优化,提高了效率。
参考文章
Bellman-Ford算法
最短路径——Bellman-Ford算法
【墙裂推荐】Bellman Ford 单源最短路径算法 视频【中字】
负权回路
介绍案例之前,我们需要知道Bellman-Ford算法有两个特点,一个是它的每条路径都有方向,另一个就是有负权回路(negative cycle),所以没有负权回路的话介意不要用这个算法。另外,Bellman-Ford算法虽然能够检测出负权回路,但是处在负权回路内以及周边被影响的那些节点,都不能计算出最短路径,因为cost越算值越小。
如下图,负权回路就是从0节点到2节点每转一圈cost值还减少了,那转个无数圈就变成负无穷了,这样最短路径就是无解的。
Bellman-Ford案例
因为没有找到合适的图,采用了参考文章当中B站上的一个图,图示有10个节点,所以我们我们需要进行9次的松弛操作,我在这里管它叫迭代
第一次迭代
初始状态的话,节点0自己到自己cost为0,到其他节点均为无穷
从节点0到节点1的cost为5,所以节点0到节点1的cost更新为5
从节点1到节点2的cost为20,所以节点0到节点2的cost更新为5+20=25
将所有的边都跟上面操作一样更新一遍,一旦出现更小的cost值的话就将之前的给替换掉
所有边都更新一遍cost的操作叫作迭代(Iteration),以下的图才是第一次迭代完的cost图,我们还需要迭代8次
第二次迭代
下图是第二次迭代的结果,我们跳过剩下的迭代直接进入最后一次迭代的图
第九次迭代
下图是第九次迭代的结果,因为图中有负权回路,所以我们再重复一次V-1=9次的迭代,直到把这个负权回路的影响传播到整张图上的所有节点
负权回路的第一次迭代
因为这一次迭代前往节点3的cost较之前更小,所以将节点3的cost值更新为负无穷
接着节点4也被影响到了,到节点4的cost值变小,所以将4节点的cost值也更新为负无穷
同样的,节点2和9也不能幸免,cost值都更新为负无穷
负权回路的第九次迭代
像上面的迭代,我们总共要执行9次,最后得出的图如下所示,节点2、3、4、9因为负权回路直接或间接的影响,求最短路径无解,其他节点的最短路径cost都已经计算出来并且不会改变了