点击上方蓝字,关注我们
道路千万条,安全第一条。
行车不规范,亲人两行泪。
假如你是刘启,带领救援队去杭州地下城送火石,车载导航被moss远程控制了,你翻出19年泛黄的地图……
不识路啊,这咋整啊?
在平时我们使用导航时,在已知起点和终点的情况下,导航总能在复杂的道路中为我们找到一条最短的道路。在这个过程中,我们可以将道路简化抽象成一个由点与点之间的连线构成的图。
每个路口都可以看作是图的顶点,顶点之间的连线代表实际中两路口间的道路,而图的边的权则代表道路的长度。若图的边有一个指向,则此图为有向图,且若A→B,则代表有路从A到B。这样,导航做的事其实就是给定图中两点,找到一条连接两点的最短路。
上述问题即图最短路径问题,它一直是图论里面一个重要问题。用于解决这个问题的算法有很多种。今天我们给大家介绍一种非常经典的算法——Dijkstra算法。
这个算法是由图灵奖得主Dijkstra提出的,得到了广泛的应用。这种有着30年历史的算法是一种典型的贪婪算法。简单来说,这个算法的核心思想就是在每一步都选取最短的一条路径,不考虑之后的状况。
Dijstra算法
若给定一个图,我们想知道从点A到其它点的最短路径长度,则Dijkstra算法的具体步骤是:
1.生成一个表,表中记录了两组数据。一组是图中其它点到点A的已知最短距离d,另一种代表此距离是否即为最短距离(0代表存疑,1代表是)。表的初始数据为:若A可直接到达点C(不经过其它点),则A→C的距离为边的权,否则为∞。初始所有顶点存疑。
2.选择一个顶点X,它是表中所有存疑顶点中具有最小的d的点。然后对于X能直接到达的每个点(如Y),考虑路径A→X→Y的长度,若小于表中Y的d,则更新此数据。最后顶点X的数据0更新为1。
3.如此遍历,当没有存疑顶点时(均为1),整个算法执行完毕,则所有顶点到已知顶点A的最小距离都被找到了。
举个栗子(๑• . •๑)
已知如图
这是初始化时的情况
假设我们以V1为起始顶点,则表的初始数据如下
接下来访问距离最短的V3,发现一条V1→V3→V4的路径,更新V4的d
访问V5(存疑的顶点中v最小的),此时到V6有一条V1→V5→V6的路径,长度为90,所以更新V6的d,同时V4也要更新
访问V4,再次更新V6
访问V6
最后因为以V2位终点的边,所以算法结束,得出了其他点到V1的最短距离。
那么问题来了,为什么Dijkstra算法是有效的,其每一步的意义何在呢?
其实算法的原理很简单:
每一步都是从选定的点的一个向外的路径探索过程。则在一次更新完成后,此时存疑的顶点中的d最小的顶点到选定点的最短路径即为最短。
若不是这样,则对于其最短路径,它从选定点出发,必会经过探索到的路径,但此段路径的长度已经不小于上述路径了。
C语言实现
那么,如何用C语言实现这个算法呢?
简单来说,上述程序的功能是:
● 将顶点按0、1…顺序编号。
● 第一行输入顶点个数与边的数量。
● 下面每行代表一条边,有三个数字,分别代表边的起点、终点、长度。
● 最后一行输入起始顶点的编号。
● 则输出是按字典序的起始顶点到其它顶点的最短距离(输出-1代表两点间没有路径)。
再举个栗子(´・ω・`)
已知如图
用邻接矩阵的方式输入这个图
8是顶点个数,11是边的条数,最后的3是以3为起点
最后以字典序输出了其余顶点到3的距离,其中-1表示没有从起点到这个顶点的路。
大家可以试试在上述程序的基础上扩充些内容,使能够输给定点到其它点的最短路径长度及其相应的路径。
当然最短路径问题还有其它种种算法(Floyd算法、Bellman-Ford算法等),可以自行了解比较各种算法的优劣与核心原理哟٩(๑> v
最后悄咪咪说句:
祝大家开学快乐(❁´ω`❁)*✲゚*~
撰写:李唯贤
排版:T桐子yo
数学建模,封印解除!