Dijkstra算法流程(适合掌握思想但是不会写代码的人阅读)

Dijkstra算法流程(适合掌握思想但是不会写代码的人阅读)

因为看了其他博主的一篇博客写的Dijkstra算法,他的算法有点小问题,所以干脆自己写个博客,记录一下debug一个小时的艰辛历程。

算法流程

第一步 建立邻接矩阵Map[N][N](邻接表)标记数组vis[N]用来标记元素是否成为定点 dis[N]表示到源点的距离
第二步 初始化第一步中的数组
第三步 通过(!vis[j]&&Map[Mindex][j]+dis[Mindex]<dis[j])这个条件修改dis数组,dis[终点]就是要求的值

解释全写在代码的注释里,如果想了解代码思想的大佬可以去这篇博客看一下,不过他的代码有点小瑕疵
(!vis[j]&&Map[Mindex][j]+dis[Mindex]<dis[j])这个条件他漏掉了条件!vis[j]
但是他的图解和思路很清晰
[https://blog.csdn.net/lbperfect123/article/details/84281300]

第一步建表

#include <iostream>
#include <cstring>
#define INF 0x3f3f3f3f
using namespace std;
int Map[2505][2505];
int dis[2505];
int vis[2505];

第二步初始化

int n,m,Start,End;
    cin >> n >> m >> Start >> End;//n表示点的个数,m表示边的个数,Start是起点,End是终点
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){//到自己的距离设为0,其他的设为无穷大
            if(i==j)
                Map[i][j]=0;
            else
                Map[i][j]=INF;
        }
    }
    int s,t,w;//s起点,t终点,w权值
    for(int i=0;i<m;i++){
        cin >> s >> t >> w;
        if(Map[s][t]>w){//因为两点之间可能有多条路,我们肯定要取最短的那条
            Map[s][t] = w;
            Map[t][s] = w;
        }
    }
    for(int i=1;i<=n;i++){//先将dis数组中和源点有边相连的点设成边长,不直接相连的设成无穷大
        dis[i] = Map[Start][i];
    }
    memset(vis,0,sizeof(vis));
    vis[Start] = 1;

第三步,修改dis数组的值

    for(int i=1;i<n;i++){//遍历n-1次,把除了源点的其他点都标记才结束
        int Min = INF,Mindex;
        for(int j=1;j<=n;j++){//从未标记的数组中找到最小值的下标
            if(!vis[j]&&dis[j]<Min){
                Mindex = j;
                Min = dis[j];
            }
        }
        vis[Mindex] = 1;//将最小值的下标加入标记
        for(int j=1;j<=n;j++){
            if(!vis[j]&&Map[Mindex][j]+dis[Mindex]<dis[j])//如果能以此次标记的点为桥梁,让未标记的点到源点的距离变短
            //那么未标记的点到源点的距离修改为此次标记的点到源点的距离加此次标记的点到未标记的点的距离
                dis[j] = Map[Mindex][j]+dis[Mindex];
        }
    }
    cout <<dis[End];//输出dis[终点]即可

完整代码

#include <iostream>
#include <cstring>
#define INF 0x3f3f3f3f
using namespace std;
int Map[2505][2505];
int dis[2505];
int vis[2505];
int n,m,Start,End;
void Init(){
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(i==j)
                Map[i][j]=0;
            else
                Map[i][j]=INF;
        }
    }
    int s,t,w;
    for(int i=0;i<m;i++){
        cin >> s >> t >> w;
        if(Map[s][t]>w){
            Map[s][t] = w;
            Map[t][s] = w;
        }
    }
    for(int i=1;i<=n;i++){
        dis[i] = Map[Start][i];
    }
    memset(vis,0,sizeof(vis));
    vis[Start] = 1;
}
void Dijkstra(){
for(int i=1;i<n;i++){
        int Min = INF,Mindex;
        for(int j=1;j<=n;j++){
            if(!vis[j]&&dis[j]<Min){
                Mindex = j;
                Min = dis[j];
            }
        }
        vis[Mindex] = 1;
        for(int j=1;j<=n;j++){
            if(!vis[j]&&Map[Mindex][j]+dis[Mindex]<dis[j])
                dis[j] = Map[Mindex][j]+dis[Mindex];
        }
    }}
int main()
{

    cin >> n >> m >> Start >> End;
    Init();
    Dijkstra();
    cout <<dis[End];

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值