学习笔记-迪杰斯特拉算法求最短路径

求最短路径问题

在这里插入图片描述

迪杰斯特拉算法

迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个结点到其他结点的最短路径。它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止。

  1. 设置出发顶点为 v,顶点集合 V{v1,v2,vi…},v 到 V 中各顶点的距离构成距离集合 Dis,Dis{d1,d2,di…},Dis集合记录着 v 到图中各顶点的距离(到自身可以看作 0,v 到 vi 距离对应为 di)
  2. 从 Dis 中选择值最小的 di 并移出 Dis 集合,同时移出 V 集合中对应的顶点 vi,此时的 v 到 vi 即为最短路径
  3. 更新 Dis 集合,更新规则为:比较 v 到 V 集合中顶点的距离值,与 v 通过 vi 到 V 集合中顶点的距离值,保留值较小的一个(同时也应该更新顶点的前驱节点为 vi,表明是通过 vi 到达的)
  4. 重复执行两步骤,直到最短路径顶点为目标顶点即可结束

图解过程

第一步,从起始点g开始,访问g的所以相邻顶点,g设为已访问
在这里插入图片描述
一步过后,距离数组更新,选择距离最小的A,把A当作顶点,访问A的所有相邻未访问顶点,把A设为已访问。
在这里插入图片描述
由于gab这条路是7大于了gb3,就保留gb这条路。接下来在没访问过的节点里找路径最短的,发现是e,把e当作顶点,访问e的所有相邻未访问顶点,把e设为已访问。
在这里插入图片描述
两条路都不是最短的,都不保留,在没访问过的节点里找路径最短的,发现是b,把b当作顶点,访问b的所有相邻未访问顶点,把b设为已访问。
在这里插入图片描述
在没访问过的节点里找路径最短的,发现是F,把F当作顶点,访问F的所有相邻未访问顶点,把F设为已访问。
在这里插入图片描述
GFD比GBD短,更新为最短,在没访问过的节点里找路径最短的,发现是C,把C当作顶点,访问C的所有相邻未访问顶点,把C设为已访问。由于C的相邻节点都已经访问,就寻找下一个最短路径节点D,D的相邻节点也都访问,这时候每个节点都被访问过,退出程序,得到结果。

简单来说

迪杰斯特拉算法求最短路径的大概思路是,从第一个点开始,找它的所有相邻点(广度优先思想),记录累计路径值(第一次就是他们自己),找到这些路径值里最小的那个点(A),让它作为第二个点,从它开始,找到它的所有相邻点(当然可能有重复的),记录累计路径值(累计了第一个点(G)到第二个点(A)的路径值),找出并保留对每个相邻点最小的累计路径值,然后找到这些累计路径值里最小的那个点,让它作为第三个点,继续重复,直到每个点都作为过顶点(作为过顶点就认为它被访问过)。

代码

编写算法辅助类,该类由三个数组组成,
visit存放图的全部顶点,用来记录各个顶点的访问情况,0表示未访问1表示已访问,初始化时其他顶点都为0,传入的起始顶点为1表示已访问;
dis,长度和顶点个数相同,存放起始顶点到对应顶点的累计距离,初始化时其他位是一个极大数,代表路径暂时不通,起始顶点对应位数是0,代表自己到自己是0,对应上图每条线的蓝色数字和;
pre,存放各顶点的前驱顶点,用于记录最短路径,初始化时每位为-1,代表无前驱,对应上图每条线的蓝色字母,有几个顶点,就有几条路径,但是不必从头到尾记录一条路径,因为如上图,路径像树一样,只要记录直接前驱,就可以顺着一直找到根,因此用一个一维数组记录每一个顶点的直接前驱下标,然后到对应下标位置在找它的前驱,一直找到-1表示根的位置,就可以还原出一条路径。

辅助类需要具有的方法:

  1. 对三个数组初始化的方法,需要获得起始顶点下标,顶点个数
  2. 判断某顶点是否被访问
  3. 更新起始顶点到某顶点的距离为新值
  4. 获得起始顶点到某顶点的累计距离
  5. 更新某顶点的前驱顶点为某值
  6. 找到应该访问的下一个顶点。规则是,查找dis距离数组,找到未被访问过且距离最小的顶点,它就为应该访问的下一个顶点,把它设置成已访问。
  7. 输出三个数组,并输出每一条最短路径
//已访问顶点集合,用于帮助完成算法,辅助类
class VisitedVertex{
   
    int[] visit;//存放顶点,0未访问1已访问
    int[] dis;//存放出发顶点到各顶点的累计距离
    int[] pre;//存放各顶点的前驱顶点

    /**
     * 初始化方法,对三个数组初始化
     * @param index 代表起始顶点
     * @param num 顶点个数
     */
    public VisitedVertex(
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
迪杰斯特拉算法是一种用于最短路径的经典算法。它可以计算一个节点到其他所有节点的最短路径。下面是一个使用C++实现的迪杰斯特拉算法最短路径的示例[^1]: ```cpp #include <iostream> #include <limits.h> #define V 9 int minDistance(int dist[], bool sptSet[]) { int min = INT_MAX, min_index; for (int v = 0; v < V; v++) { if (sptSet[v] == false && dist[v] <= min) { min = dist[v]; min_index = v; } } return min_index; } void printSolution(int dist[]) { std::cout << "Vertex \t\t Distance from Source" << std::endl; for (int i = 0; i < V; i++) { std::cout << i << " \t\t " << dist[i] << std::endl; } } void dijkstra(int graph[V][V], int src) { int dist[V]; bool sptSet[V]; for (int i = 0; i < V; i++) { dist[i] = INT_MAX; sptSet[i] = false; } dist[src] = 0; for (int count = 0; count < V - 1; count++) { int u = minDistance(dist, sptSet); sptSet[u] = true; for (int v = 0; v < V; v++) { if (!sptSet[v] && graph[u][v] && dist[u] != INT_MAX && dist[u] + graph[u][v] < dist[v]) { dist[v] = dist[u] + graph[u][v]; } } } printSolution(dist); } int main() { int graph[V][V] = {{0, 4, 0, 0, 0, 0, 0, 8, 0}, {4, 0, 8, 0, 0, 0, 0, 11, 0}, {0, 8, 0, 7, 0, 4, 0, 0, 2}, {0, 0, 7, 0, 9, 14, 0, 0, 0}, {0, 0, 0, 9, 0, 10, 0, 0, 0}, {0, 0, 4, 14, 10, 0, 2, 0, 0}, {0, 0, 0, 0, 0, 2, 0, 1, 6}, {8, 11, 0, 0, 0, 0, 1, 0, 7}, {0, 0, 2, 0, 0, 0, 6, 7, 0}}; dijkstra(graph, 0); return 0; } ``` 这段使用邻接矩阵表示图,其中`V`表示节点的数量。通过调用`dijkstra`函数,可以计算从源节点到其他所有节点的最短路径,并将结果打印出来。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值