首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >最短路径问题--迪杰斯特拉(Dijkstra)算法

最短路径问题--迪杰斯特拉(Dijkstra)算法

作者头像
用户6021899
发布2021-04-19 15:18:17
发布2021-04-19 15:18:17
9420
举报

迪杰斯特拉(Dijkstra)算法是典型的用来解决最短路径的算法,也是很多教程中的范例,由荷兰计算机科学家狄克斯特拉于1959年提出,用来求从起始点到其他所有点最短路径。该算法采用了贪心的思想,每次都查找与该点距离最近的点,也因为这样,它不能用来解决存在负权边的图。解决的问题大多是这样的:有一个无向图G(V,E),边E[i]的权值为W[i](正数),找出V[0]到V[i]的最短路径。

算法步骤:

  • 通过Dijkstra计算图G中的最短路径时,需要指定起点s(即从顶点s开始计算)。
  • 此外,引进两个集合S和U。S的作用是记录已求出最短路径的顶点(以及相应的最短路径长度),而U则是记录还未求出最短路径的顶点(以及该顶点到起点s的距离)。
  • 初始时,S中只有起点s;U中是除s之外的顶点,并且U中顶点的路径是”起点s到该顶点的路径”。然后,从U中找出路径最短的顶点,并将其加入到S中;接着,更新U中的顶点和顶点对应的路径。然后,再从U中找出路径最短的顶点,并将其加入到S中;接着,更新U中的顶点和顶点对应的路径。… 重复该操作,直到遍历完所有顶点。

可以去B站观看迪杰斯特拉的动画演示:https://www.bilibili.com/video/BV1q4411M7r9/?spm_id_from=333.788.videocard.0

下面给出该算法的源代码:

代码语言:javascript
复制
#include <iostream>
#include <string>
#include <vector>
#include <iomanip>
#define INF 999999999.9
using namespace std;
vector<float>Dijkstra(vector<vector<float>>&graph, int start);

int main()
{
    string nodes[6] = {"北京","天津","郑州","济南","长沙","海口"};
    int n = 6; //顶点数// 0北京,1天津,2郑州,3济南,4长沙,5海口
    vector<vector<float>>graph;//样例中对于的邻接矩阵

    for(int i=0;i<n;i++){
        graph.push_back(vector<float>());
        for(int j=0;j<n;j++){
            graph[i].push_back(INF);
        }
        graph[i][i] = 0.0;
    }
    graph[0][1]=100.0;//北京 到 天津
    graph[1][0]=100.0;
    graph[1][2]=900.0;//天津 到 郑州
    graph[2][1]=900.0;
    graph[1][3]=300.0;//天津 到 济南
    graph[3][1]=300.0;
    graph[2][3]=400.0;//郑州到 济南
    graph[3][2]=400.0;
    graph[2][4]=500.0;//郑州 到 长沙
    graph[4][2]=500.0;
    graph[3][4]=1300.0;//济南 到 长沙
    graph[4][3]=1300.0;
    graph[4][5]=1500.0;//长沙 到 海口
    graph[5][4]=1500.0;
    graph[3][5]=1400.0;//济南 到 海口
    graph[5][3]=1400.0;
    
    cout<<"邻接矩阵:"<<endl;
    cout<<setw(5)<<right<<"距离"<<" ";//打印时宽度设为5,右对齐
    for(int i=0;i<n;i++){
        cout<<setw(5)<<right<<nodes[i]<<" ";//打印时宽度设为5,右对齐
    }
    cout<<endl;
    for(int i=0;i<n;i++){
        cout<<setw(5)<<right<<nodes[i]<<" ";//打印时宽度设为5,右对齐
        for(int j=0;j<n;j++){
            cout<<setw(5)<<right<<graph[i][j]<<" ";//打印时宽度设为5,右对齐
        }
        cout<<endl;
    }
    cout<<endl;
    cout<<"北京(节点0)到其它节点的最短距离:"<<endl;
    vector<float> dist = Dijkstra(graph,0);
    for(int i=0; i<n;i++){
        if(i!=0) cout<<nodes[0]<<"到"<<nodes[i]<<":"<<dist[i]<<endl;
    }
    cout<<endl;
    cout<<"郑州(节点2)到其它节点的最短距离:"<<endl;
    dist = Dijkstra(graph,2);
    for(int i=0; i<n;i++){
        if(i!=2) cout<<nodes[2]<<"到"<<nodes[i]<<":"<<dist[i]<<endl;
    }
    return 0;
}

vector<float>Dijkstra(vector<vector<float>>&graph, int start){
    //start 为起点的索引
    int n = graph.size(); //顶点个数
    vector<bool> visit(n); //已完成访问的节点
    vector<float> dist(n);//存储从起点start到其它顶点的最短路径
    for(int i=0;i<n;i++){
        dist[i] = graph[start][i];//将minDist数组初始化为最初图中的路径长度
    }
    visit[start] = true;//标记其实顶点为已访问
    for(int i=0;i<n;i++){
        float min_dist = INF;//存储从起点到其它未被访问节点中的最短距离
        int middle = 0;//存储最短距离的编号

        for(int j=0;j<n;j++){
            //如果顶点j未被访问,且dist[j] < min_dist
            if(visit[j] == false && dist[j] < min_dist){
                min_dist = dist[j];//更新最短距离为dist[j]
                middle = j;//更新中间节点编号为j
            }
        }
        //以新的middle 为中间节点,循环遍历其它所有节点
        for(int j =0; j<n; j++){
            float sum = dist[middle]+graph[middle][j];//从起始节点到middle 与从middle到节点j的距离之和
            //
            if(visit[j]==false && dist[j] > sum){
                dist[j] = sum;//更新距离为从起始节点到middle与从middle到节点j的距离之和
            }
        }
        visit[middle] = true;//节点middle 标记为已访问
    }
    return dist;//返回最短路径结果数组
}
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-04-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Python可视化编程机器学习OpenCV 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档