最短路径之基于贪心算法的迪杰斯特拉dijkstra算法(有图解,含码源)

简介: 最短路径之基于贪心算法的迪杰斯特拉dijkstra算法(有图解,含码源)

目录


迪杰斯特拉算法介绍

算法知识点

算法思路

算法前的准备

算法步骤

模板代码

例题带图解析


正文


迪杰斯特拉算法介绍


迪杰斯特拉算法(Dijkstra)是由荷兰计算机科学家狄克斯特拉于1959年提出的,因此又叫狄克斯特拉算法。是从一个顶点到其余各顶点的最短路径算法,解决的是有权图中最短路径问题。迪杰斯特拉算法主要特点是从起始点开始,采用贪心算法的策略,每次遍历到始点距离最近且未访问过的顶点的邻接节点,直到扩展到终点为止。


迪杰斯特拉算法用于查找图中某个顶点到其它所有顶点的最短路径,该算法既适用于无向加权图,也适用于有向加权图。

注意,使用迪杰斯特拉算法查找最短路径时,必须保证图中所有边的权值为非负数,否则查找过程很容易出错。


算法知识点


贪心算法是一种对某些求最优解问题的更简单、更迅速的设计技术。贪心算法的特点是一步一步地进行,常以当前情况为基础根据某个优化测度作最优选择,而不考虑各种可能的整体情况,省去了为找最优解要穷尽所有可能而必须耗费的大量时间。贪心算法采用自顶向下,以迭代的方法做出相继的贪心选择,每做一次贪心选择,就将所求问题简化为一个规模更小的子问题,通过每一步贪心选择,可得到问题的一个最优解。虽然每一步上都要保证能获得局部最优解,但由此产生的全局解有时不一定是最优的,所以贪心算法不要回溯


算法思路


通过Dijkstra计算图G中的最短路径时,需要指定一个起点D(即从顶点D开始计算)。

此外,引进两个数组S和U。S的作用是记录已求出最短路径的顶点(以及相应的最短路径长度),而U则是记录还未求出最短路径的顶点(以及该顶点到起点D的距离)。

初始时,数组S中只有起点D;数组U中是除起点D之外的顶点,并且数组U中记录各顶点到起点D的距离。如果顶点与起点D不相邻,距离为无穷大。

然后,从数组U中找出路径最短的顶点K,并将其加入到数组S中;同时,从数组U中移除顶点K。接着,更新数组U中的各顶点到起点D的距离。

重复第4步操作,直到遍历完所有顶点。


算法前的准备


需要借助三个辅助向量(数组):

       v:表示以v为下标的起点

   1.数组 s[n] 标记这个最短路径有没有被求出

       s[i] = 1; 当源点v到vi的最短路径求出

       s[i] = 0; 源点v到vi的最短路径没有被求出

     

           s[0]: 表示v->v0的最短路径有没有被求出

           s[1]: 表示v->v1的最短路径有没有被求出

           s[2]: 表示v->v2的最短路径有没有被求出

           ....

           s[i]: 表示v->vi的最短路径有没有被求出

                初始时,s[v] = 1,其它的s[i] = 0

   2.数组dist[n]  最短路径距离

 

       dist[i] 源点v到vi的最短路径长度

           初始时:

               dist[i] = <v,vi> = w;

               <v,vi>的权w,若p(v,vi)存在,表示v到vi有一条直接路径

               dist[i] = VERY_BIG ,p(v,vi)不存在,表示v到vi没有一条直接路径

             

   3.path[n]

       源点v到vi的最短路径  (v,...vi)

           初始时,path[i] = {v}


算法步骤


假设图中有n个顶点,Dijkstra是要求n-1条最短路径,即源点v到其它n-1个顶点的边(最短路径)

       step1:

           源点v到其它各个顶点的第一条最短路径长度 dis[u] = MIN{dist[w]| w= 0,1,2..n-1且s[w] = 0}

           表示:

               在所有没有被找到最短路径中找到一条最短的,这条路径当做当前求出的最短路径长度。

             

               eq: dist[B] = Min{dis[B], dist[C],dist[D]}

                   假设dist[B]为最短路径

                       即A-B (源点A)的最短路径为dist[B] 且 s[B] = 1;

                           证明:

                               A->B

                               用穷举法:

                                   A->B : dist[B]

                                   A->C->B :dist[c] + x  > dist[B]

                                   所以得证。

                                   dist[u]最为当前最短路径 s[u] = 1:表示v->u的最短路径已经被求出。

     

       step2:

           对所有s[w] = 0(其它所有未被求出的最短路径的点),更新dist[w]

               if dist[u] + <u , w> < dist[w] //说明我有一条更短的路径到w

                   dist[w] = dist[u] + <u , w> //即更新dist[w]

                 

                   把step1 step2 重复n-1次 就可以求出最短距离


模板代码


int s[MAXN];//是否已经求出最短路径的标志数组 s[i]==1 :表示v到vi最短路径已经求出 ; s[i] == 0:表示v到vi最短路径没有求出
int dist[MAXN];//存放当前源点到各顶点的最短路径长度
int path[MAXN];//存放的源点到终点i的最短路径是利用哪个最优点更新的 
//用迪杰斯特拉算法求出v点到其它各顶点的最短路径
void Dijkstra(Graph *g, int v)
{
    //step 1 初始化辅助数组
    int i;
    for( i = 0; i < g->vexnum; i++)
    {
        s[i] = 0;//一开始都为0
        dist[i] = g->Adj[v][i];//邻接矩阵权值
        path[i] = v;//每条最短路径起点都为v
    }
    s[v] = 1;
    dist[v] = 0;
    //step2 在所有没有被求出来的最短路径找出一条最短的 长度当成当前求出的最短路径
    int min;//求最优顶点的记录板
    int i_min;//最优顶点下标
    int times; //寻找最短路径的次数  每次只找一条n-1
    for(times = 0; times < g->vexnum-1; times++)
    {
        //step1 求出当前最优顶点
        min = VERY_BIG;
        for(i = 0; i < g->vexnum; i++)
        {
            if(s[i] == 0 && dist[i] < min)
            {
                min = dist[i];
                i_min = i;
            }
        }
        s[i_min] = 1;//最短路径已经求出
        //step2 根据最优顶点更新其它dist
        for(i = 0; i < g->vexnum; i++)
        {
            if(s[i] == 0)
            {
                if(dist[i_min] + g->Adj[i_min][i]  < dist[i])
                {
                    dist[i] = dist[i_min] + g->Adj[i_min][i];
                    path[i] = i_min;
                }
            }
        }
    }
}
// a -> b: 15 输出所有最短路径值
void print_dist(Graph *g, int v)
{
    int i;
    for(i = 0; i < g->vexnum; i++)
    {
        printf("the %c -> %c : %d\n",g->V[v], g->V[i], dist[i]);
    }
}
void print_path(Graph *g, int v)
{
    int i;
    for(i = 0; i < g->vexnum; i++)
    {
        if(dist[i] == VERY_BIG)
        {
            printf("%c -> %c is no path\n",g->V[v], g->V[i]);
            continue;
        }
    }
    printf("%c ->%c : %c",g->V[v], g->V[i],g->V[i]);
    int pre_index = path[i];
    while(1)
    {
        printf("%c ",g->V[pre_index]);
        if(pre_index == v)//已经回到了出发点
        {
            break;
        }
        pre_index = path[pre_index];
    }
    printf("\n");
}


例题带图解析


例题来源,自创,是笔者经过计算后,包含了大部分情况。                                                    (求A点到各点的最短路径)

0000000000000000000000000000000000000000000000000000000000.jpeg

名称解释:


       标志:为1 时表示已找到最短路径,为0 时表示还未找到最短路径


       距离:目前从A点到目的点的最短距离


       路径:目前从A点到目的点的最短路径


       --:目前无法到达


这是第一轮寻路,以A为起点。


A
B C D E F G
标志 1 0 0 0 0 0 0
距离 0 3 2 -- -- -- --
路径 A A->B A->c -- -- -- --

上述距离最短的是A->C为2,因此C的最短路径找到了,C的标志为变为1,下一轮以A->C这条路径为起点,继续寻路

第二轮寻路,以A->C为起点,图中可以看出,C继续往下走,可以到D点与F点。




A
B C D E F G
标志 1 0 1 0 0 0 0
距离 0 3 2 10 -- 6 --
路径 A A->B A->C A->C->D -- A->C->D --

比较距离时,比较的是标志位为0的有数距离,第二轮就算比较B,D,F三点距离,这里可以看到A->B距离最小,因此到B点的最小路径找到,为A->C,距离为2。下一轮以A->C这条路径为起点,继续寻路。


后面的与这两步都一样,这里就不赘述啦,就留一点给小伙伴们发挥的空间,也可以将自己后续的寻路步骤发到评论区大家一起讨论哦。互通有无,互相进步。

相关文章
|
2月前
|
存储 人工智能 算法
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
这篇文章详细介绍了Dijkstra和Floyd算法,这两种算法分别用于解决单源和多源最短路径问题,并且提供了Java语言的实现代码。
92 3
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
|
2月前
|
存储 算法 程序员
迪杰斯特拉(Dijkstra)算法(C/C++)
迪杰斯特拉(Dijkstra)算法(C/C++)
|
4月前
|
机器学习/深度学习 算法 Java
算法设计(动态规划应用实验报告)实现基于贪婪技术思想的Prim算法、Dijkstra算法
这篇文章介绍了基于贪婪技术思想的Prim算法和Dijkstra算法,包括它们的伪代码描述、Java源代码实现、时间效率分析,并展示了算法的测试用例结果,使读者对贪婪技术及其应用有了更深入的理解。
算法设计(动态规划应用实验报告)实现基于贪婪技术思想的Prim算法、Dijkstra算法
|
4月前
|
自然语言处理 算法
HanLP — HMM隐马尔可夫模型 - 路径规划算法 - 求解最短路径 - 维特比(Viterbi)算法
HanLP — HMM隐马尔可夫模型 - 路径规划算法 - 求解最短路径 - 维特比(Viterbi)算法
65 0
HanLP — HMM隐马尔可夫模型 - 路径规划算法 - 求解最短路径 - 维特比(Viterbi)算法
|
17天前
|
算法
基于WOA算法的SVDD参数寻优matlab仿真
该程序利用鲸鱼优化算法(WOA)对支持向量数据描述(SVDD)模型的参数进行优化,以提高数据分类的准确性。通过MATLAB2022A实现,展示了不同信噪比(SNR)下模型的分类误差。WOA通过模拟鲸鱼捕食行为,动态调整SVDD参数,如惩罚因子C和核函数参数γ,以寻找最优参数组合,增强模型的鲁棒性和泛化能力。
|
23天前
|
机器学习/深度学习 算法 Serverless
基于WOA-SVM的乳腺癌数据分类识别算法matlab仿真,对比BP神经网络和SVM
本项目利用鲸鱼优化算法(WOA)优化支持向量机(SVM)参数,针对乳腺癌早期诊断问题,通过MATLAB 2022a实现。核心代码包括参数初始化、目标函数计算、位置更新等步骤,并附有详细中文注释及操作视频。实验结果显示,WOA-SVM在提高分类精度和泛化能力方面表现出色,为乳腺癌的早期诊断提供了有效的技术支持。
|
3天前
|
供应链 算法 调度
排队算法的matlab仿真,带GUI界面
该程序使用MATLAB 2022A版本实现排队算法的仿真,并带有GUI界面。程序支持单队列单服务台、单队列多服务台和多队列多服务台三种排队方式。核心函数`func_mms2`通过模拟到达时间和服务时间,计算阻塞率和利用率。排队论研究系统中顾客和服务台的交互行为,广泛应用于通信网络、生产调度和服务行业等领域,旨在优化系统性能,减少等待时间,提高资源利用率。
|
11天前
|
存储 算法
基于HMM隐马尔可夫模型的金融数据预测算法matlab仿真
本项目基于HMM模型实现金融数据预测,包括模型训练与预测两部分。在MATLAB2022A上运行,通过计算状态转移和观测概率预测未来值,并绘制了预测值、真实值及预测误差的对比图。HMM模型适用于金融市场的时间序列分析,能够有效捕捉隐藏状态及其转换规律,为金融预测提供有力工具。
|
19天前
|
算法
基于GA遗传算法的PID控制器参数优化matlab建模与仿真
本项目基于遗传算法(GA)优化PID控制器参数,通过空间状态方程构建控制对象,自定义GA的选择、交叉、变异过程,以提高PID控制性能。与使用通用GA工具箱相比,此方法更灵活、针对性强。MATLAB2022A环境下测试,展示了GA优化前后PID控制效果的显著差异。核心代码实现了遗传算法的迭代优化过程,最终通过适应度函数评估并选择了最优PID参数,显著提升了系统响应速度和稳定性。
|
11天前
|
机器学习/深度学习 算法 信息无障碍
基于GoogleNet深度学习网络的手语识别算法matlab仿真
本项目展示了基于GoogleNet的深度学习手语识别算法,使用Matlab2022a实现。通过卷积神经网络(CNN)识别手语手势,如&quot;How are you&quot;、&quot;I am fine&quot;、&quot;I love you&quot;等。核心在于Inception模块,通过多尺度处理和1x1卷积减少计算量,提高效率。项目附带完整代码及操作视频。