实例讲解Dijkstra算法,代码实现求最短路径并记录路径

Dijkstra算法

文字简述:Dijkstra算法算是贪心思想实现的。首先把起点到所有点的距离中找到最短的,然后松弛一次再找出最短的,这样把所有的点找遍之后就存下了起点到其他所有点的最短距离。
松弛操作:松弛即更新。把刚刚找到的距离最短的点作为中转站再遍历一遍看看会不会更近,如果更近了就更新距离。

算法流程图
在这里插入图片描述

实例演示Dijkstra算法
在这里插入图片描述
例:求1到每个点的最短路径
1.将起点放入容器:容器A:1(0);括号内表示最短路径
找出与 容器A 内的点距离最小的点:2;
注意:找出的点不能是容器A内的
将2放入已确定最短路径点的集合中,更新容器A:1(0),2(1);

2.找出与 容器A 内的点距离最小的点(此时容器A内有两个点):4
将4放入容器A中,更新容器:1(0),2(1),4(4);

3.找出与 容器A 内的点距离最小的点(此时容器A内有三个点):3
将4放入容器A中,更新容器A:1(0),2(1),4(4),3(8);

4.找出与 容器A 内的点距离最小的点(此时容器A内有四个点):5
将5放入容器A中,更新容器A:1(0),2(1),4(4),3(8),5(13);

5.找出与 容器A 内的点距离最小的点(此时容器A内有五个点):6
将6放入容器A中,更新容器A:1(0),2(1),4(4),3(8),5(13),6(17);

求最短路径并记录路径代码如下:

程序结果截图:
在这里插入图片描述
IDE:VS2019
C++

#include<stack>
#include<iostream>
using namespace std;
const int N = 100;
const int INF = 100000;
int p[N][N], d[N], path[N];      
//分别存结点  距离 路径

void dijkstra(int bgn, int n)    //bgn为出发节点,n表示图中节点总数
{
    int i, j, min, min_num;
    int mark[N] = { 0 };//标记为未确认
    //更新初始距离
    for (i = 1; i <= n; i++)
    {
        d[i] = p[bgn][i];
    }
    mark[bgn] = 1; d[bgn] = 0;

    for (i = 1; i <n; i++)
    {
        min = INF;
        //找到距离起点最近的点存在min_num,其距离存在min
        for (j = 1; j <= n; j++)
        {
            if (!mark[j] && d[j] < min)
            {
                min = d[j];
                min_num = j;
            }
        }
        mark[min_num] = 1;//标记为已确认
        //更新最短路径并记录最后一个中途结点
        for (j = 1; j <=n; j++)
        {
            if (d[j] > min + p[min_num][j])
            {
                path[j] = min_num;//path[j]记录d[j]暂时最短路径的最后一个中途节点min_num,表明d[j]最后一段从节点min_num到节点j
                d[j] = min + p[min_num][j];
            }
        }
    }
}
void print(int bgn, int n)       //bgn为出发节点,n表示图中节点总数
{
    int i, j;
    stack<int> q;               //由于记录的中途节点是倒序的,所以使用栈(先进后出),获得正序
    for (i = 2; i <=n; i++)            //打印从出发节点到各节点的最短距离和经过的路径
    {
        j = i;
        while (path[j] != -1)      //如果j有中途节点
        {
            q.push(j);          //将j压入堆
            j = path[j];          //将j的前个中途节点赋给j
        }
        q.push(j);
        cout << bgn << "=>" << i <<" length:"<< d[i]<<" path  " << bgn;
        while (!q.empty())       //先进后出,获得正序
        {
            cout << q.top();
            //printf("%d ", q.top());//打印堆的头节点
            q.pop();            //将堆的头节点弹出
        }
        printf("\n");
    }
}
int main()
{
    memset(path, -1, sizeof(path));//将path数组初始化为-1
    int i, j, n = 6;  //n为顶点个数,方便测试将数据写死
    //任意两点间距离初始化为INF,自身为0
    for (i = 1; i <= n; i++)
    {
        for (j = 1; j <=n; j++)
        {
            p[i][j] = (i == j ? 0 : INF);
        }
    }
    //为方便测试将数据写死,下面注释内为如何输入数据
    p[1][2] = 1; p[1][3] = 12; p[2][3] = 9; p[2][4] = 3; p[4][5] = 13; p[3][5] = 5; p[4][6] = 15; p[5][6] = 4;p[4][3]=4;//p[i][j]表示节点i到节点j的距离 
    /*
     int vtx, side;//顶点总数 边总数
    cin >>vtx>>side;
    int vtx_1,vtx_2,dist;//点 距离
    for(int i=0;i<side;i++){
        cin>>vtx_1>>vtx_2>>dist;
        p[vtx_1][vtx_2]=dist;
    }
    若输入数据请注意修改上面的顶点数
    */
    dijkstra(1, n);               //求从节点0出发到各节点的最短距离
    print(1, n);                  //打印从节点0出发到各节点的最短距离和路径
    return 0;
}

欢迎指正 畅所欲言
既来之,则赞之~

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值