迪杰斯特拉(Dijkstra)算法求最短路径

一.最短路径

  • 从某顶点(源点)出发到另一顶点(目的地)的路径中,有一条各边(或弧)权值之和最小的路径称为最短路径
  • 迪杰斯特拉算法:从单原点到其余各店的最短路径

二.基本思想

依最短路径的长度递增的次序求得各条路径。其中,从源点到顶点v的最短路径是所有最短路径中长度最短者

  • 路径长度最短的最短路径的特点:
    在这条路上,必定只含一条弧,并且这条弧的权值最小(记为v0->v1)
  • 下一条路径长度次短的最短路径的特点:
    或者是直接从源点到该点(只含一条弧)
    或者是从源点经过顶点v1,再到达该顶点(由两条弧组成)(v0->v1->v2)
  • 再下一条路径长度次短的的最短路径的特点:
    或者是直接从源点到该点(只含一条弧)
    或者是从源点经过顶点v1,再到达该顶点(由两条弧)
    或者是从源点经过顶点v2,再到达该顶点(看v2的情况,第一种就两条弧,第二种就三条弧)
  • 重复步骤

三.步骤图解

在这里插入图片描述
在这里插入图片描述

步骤:

S中存放的是已经求得的最短路径的终点的集合,v-s集合包含其他点
i代表第i条最短路径(及可能路径走法)
邻接矩阵表示弧<vi,vj>上的权值
dist[i]值

若vi在S中,dist[i]表示源点到vi的最短路径长度
若vi在V-S中,dist[i]表示源点到vi的只包括S中的顶点为中间顶点的最短路径

  1. 找路径长度最短的最短路径,首先看从0开始弧度为1的点,列出即为v0->v2,v0->v4,v0->v5.以及它们的权值(即表格第一列)在第一列中找出第一条最短路径是v0->v2权值为10,画上对号。那么此时v0到v2的最短路径就找到了,v2一行可以省略了
  2. 继续以v2为顶点查找下一步可行路线,由邻接矩阵或者直接看图找,可得v0->v2->v3将此路线及它的权值与之前找到的最短路径(第一列剩下的路径)做比较,即从V-S中找出路径最短的顶点(即为v4),并将其加入到S中;接着,更新V-S中的顶点和顶点对应的路径(即第三步以v4为顶点查找)
  3. 以v4为顶点查找下一步,与上相同,从V-S中找出路径,相互比较,找出最小的(v3),并将其加入到S中;接着,更新V-S中的顶点和顶点对应的路径。
  4. 重复步骤,最终完成,找出来每次的最短路径,将所有可以到达的点都包含在S中。

四.代码说明

    /*
 * Dijkstra最短路径。
 * 即,统计图(G)中"顶点vs"到其它各个顶点的最短路径。
 *
 * 参数说明:
 *        G -- 图
 *       vs -- 起始顶点(start vertex)。即计算"顶点vs"到其它顶点的最短路径。
 *     prev -- 前驱顶点数组。即,prev[i]的值是"顶点vs"到"顶点i"的最短路径所经历的全部顶点中,位于"顶点i"之前的那个顶点。
 *     dist -- 长度数组。即,dist[i]是"顶点vs"到"顶点i"的最短路径的长度。
 */
void dijkstra(Graph G, int vs, int prev[], int dist[])
{
    int i,j,k;
    int min;
    int tmp;
    int flag[MAX];      // flag[i]=1表示"顶点vs"到"顶点i"的最短路径已成功获取。
 
    // 初始化
    for (i = 0; i < G.vexnum; i++)
    {
        flag[i] = 0;              // 顶点i的最短路径还没获取到。
        prev[i] = 0;              // 顶点i的前驱顶点为0。
        dist[i] = G.matrix[vs][i];// 顶点i的最短路径为"顶点vs"到"顶点i"的权。
    }
 
    // 对"顶点vs"自身进行初始化
    flag[vs] = 1;
    dist[vs] = 0;
 
    // 遍历G.vexnum-1次;每次找出一个顶点的最短路径。
    for (i = 1; i < G.vexnum; i++)
    {
        // 寻找当前最小的路径;
        // 即,在未获取最短路径的顶点中,找到离vs最近的顶点(k)。
        min = INF;
        for (j = 0; j < G.vexnum; j++)
        {
            if (flag[j]==0 && dist[j]<min)
            {
                min = dist[j];
                k = j;
            }
        }
        // 标记"顶点k"为已经获取到最短路径
        flag[k] = 1;
 
        // 修正当前最短路径和前驱顶点
        // 即,当已经"顶点k的最短路径"之后,更新"未获取最短路径的顶点的最短路径和前驱顶点"。
        for (j = 0; j < G.vexnum; j++)
        {
            tmp = (G.matrix[k][j]==INF ? INF : (min + G.matrix[k][j])); // 防止溢出
            if (flag[j] == 0 && (tmp  < dist[j]) )
            {
                dist[j] = tmp;
                prev[j] = k;
            }
        }
    }
 
    // 打印dijkstra最短路径的结果
    printf("dijkstra(%c): \n", G.vexs[vs]);
    for (i = 0; i < G.vexnum; i++)
        printf("  shortest(%c, %c)=%d\n", G.vexs[vs], G.vexs[i], dist[i]);
}



参考文章
文章中附有迪杰斯特拉(Dijkstra)算法源码

  • 32
    点赞
  • 188
    收藏
    觉得还不错? 一键收藏
  • 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、付费专栏及课程。

余额充值