>算法笔记-动态规划-最短路径迪杰斯特拉算法
算法笔记-动态规划-最短路径迪杰斯特拉算法
作者:星河滚烫兮
前言
图的最短路径问题在现实生活中有很广阔的应用,最短路径又分为单源最短路径与多源最短路径,前者求出固定起点到其他节点的最短路径,后者求出可变起点到其他节点的最短路径。同时,又有多种思想来求解,比如贪心算法与动态规划求解最短路径,前者求得局部最优解,时间复杂度与空间复杂度低代价小,被广泛应用;后者求得全局最优解,但时间复杂度与空间复杂度相对高,本文迪杰斯特拉算法便是动态规划思想。
迪杰斯特拉算法设置动态规划数组dp,根据最优化策略进行状态转移,更新dp数组(保存状态)。该算法描述与过程均放在代码注释中,大家结合代码与注释学习。
以下是代码使用的图示例:
C代码
/*这里我们关心算法的实现而淡化图这种数据结构的表示,所以我们这里用简化的邻接矩阵表示邻接矩阵G与dp数组我们定义为全局变量(在写大型工程时不要这么做)由于我们将两个dp数组设置为定长,增加了判断-1的时间,所以我们程序的时间复杂度达到了O(n3),可以把两个dp数组设置为变长则缩短至O(n2),大家可以自己动手试试
*/
#include<stdio.h>
#include<stdlib.h> // 使用malloc函数
#define INFINITY 65535 // 定义正无穷
#define MAXSIZE 10 // 定义最大节点数
enum Nodes{A, B, C, D, E}; // 令A,B,C,D,E作为常量,分别等于邻接矩阵下标0,1,2,3,4typedef struct{int matrix[MAXSIZE][MAXSIZE];int size; // 节点数
}Graph; // 创建简化版邻接矩阵数据结构
typedef struct{int index;int value;
}elem; // 模拟字典的数据结构方便函数返回键值对typedef struct{int *dp_com; // 已确定最短路径的节点集合int *dp_row; // 未确定最短路径的节点集合int length;
}Dp; // 创建双dp数组数据结构
Dp dp;/*邻接矩阵初始化
*/
Graph G = {{{0,30,20,10,INFINITY},{30,0,INFINITY,10,5},{20,INFINITY,0,5,20},{10,10,5,0,10},{INFINITY,5,20,10,0}}, 5};
/* 双动态规划数组初始化
*/
void dp_Init(Graph g, int start, Dp *p) // 注意:这里不能让指针直接指向G的某一行,因为那样操作dp时也会修改G
{int i;p->length = g.size;p->dp_com = (int *)malloc(sizeof(int)*g.size);p->dp_row = (int *)malloc(sizeof(int)*g.size);for(i=0;i<g.size;i++)p->dp_row[i] = g.matrix[start][i]; // -1代表为空for(i=0;i<g.size;i++)p->dp_com[i] = -1; // -1代表为空
}
/*输出dp数组
*/
void dp_display(Dp dp)
{int i;printf("\tdp_complete: {");for(i=0;i<G.size;i++){if(dp.dp_com[i]==INFINITY)printf("∞ ");elseprintf("%d ",dp.dp_com[i]);}printf("\b}\n");printf("\t dp_row : {");for(i=0;i<G.size;i++){if(dp.dp_row[i]==INFINITY)printf("∞ ");elseprintf("%d ",dp.dp_row[i]);}printf("\b}\n");
}
/*输出邻接矩阵
*/
void GraphDisplay(Graph g)
{for(int i=0; i<g.size; i++){for(int j=0; j<g.size; j++){if(g.matrix[i][j]==INFINITY)printf("∞ ");elseprintf("%d ",g.matrix[i][j]);}printf("\n");}
}
/*获得数组最小值
*/
elem getmin(Dp dp)
{elem min={-1, INFINITY};for(int i=0; i<dp.length;i++)if(dp.dp_row[i]!=-1&&dp.dp_row[i]<min.value){min.index = i;min.value = dp.dp_row[i];}return min;
}
/*子最短路径更新
*/
void SubOptimizition(Graph g, Dp *dp) // 动态规划子问题最优化过程:根据dp_com更新dp_row数组各元素
{for(int i=0; i<dp->length; i++){if(dp->dp_row[i]!=-1)for(int j=0; j<dp->length; j++){if(dp->dp_com[j]!=-1) if(dp->dp_com[j]+g.matrix[j][i]<dp->dp_row[i]) // 更新row数组达到最优化过程dp->dp_row[i] = dp->dp_com[j]+g.matrix[j][i];}}
}
/*
路径规划过程:->选取当前最短子路径min(dp_row)的索引与值即键值对->用该最短子路径更新对应dp_com位置,同时该dp_row位置置为-1表示不存在为空->使用刚刚更新后的dp_com数组,最优化dp_row数组,完成状态转移->返回第一步重复,直至dp_row数组全空
*/
void PathProgram(Graph g, Dp *dp) // 路径规划过程:选取当前最短路径min(dp_row)
{elem i = getmin(*dp);while (i.value!=INFINITY){dp->dp_com[i.index] = i.value;dp->dp_row[i.index] = -1;SubOptimizition(g,dp);i = getmin(*dp);}}int main()
{dp_Init(G,A,&dp);printf("图的邻接矩阵如下:\n");GraphDisplay(G);printf("初始时的dp数组:\n");dp_display(dp);PathProgram(G,&dp);printf("结束时的dp数组:\n");dp_display(dp);
}
>算法笔记-动态规划-最短路径迪杰斯特拉算法相关推荐
- 最短路径——迪杰斯特拉算法——图的数据结构
最短路径是在工程上经常用到的概念,在这里给出了从单源点到任意顶点的迪杰斯特拉算法. 先来看看基本概念: 用代码C语言实现如下: #include<string.h>#include< ...
- 最短路径迪杰斯特拉算法--邻接矩阵
一.算法介绍 迪杰斯特拉算法(解决单源最短路径) 基本思想:每次找到离源点(如1号节点)最近的一个顶点,然后以该顶点为中心进行扩展,最终得到源点到其余所有点的最短路径. 基本步骤:1,设置标记数组bo ...
- 算法与数据结构(六) 迪杰斯特拉算法的最短路径(Swift版)
上篇博客我们详细的介绍了两种经典的最小生成树的算法,本篇博客我们就来详细的讲一下最短路径的经典算法----迪杰斯特拉算法.首先我们先聊一下什么是最短路径,这个还是比较好理解的.比如我要从北京到济南,而 ...
- 别说了,世界那么大我想去看看!(最短路径-迪杰斯特拉算法弗洛伊德算法)
前言: 一直想去外面的世界看看,中国城市那么多,那么美,怎么样才可以用最少的钱,最短的时间游遍我想去的城市呢?(我在做梦?不不不!迪杰斯特拉算法和弗洛伊德算法来了) 这两个算法有着广泛的用途 ...
- 常用算法(八)——迪杰斯特拉算法
迪杰斯特拉算法 大纲目录 迪杰斯特拉算法 迪杰斯特拉算法 一.应用场景-最短路径问题 二.迪杰斯特拉(Dijkstra)算法介绍 三.迪杰斯特拉(Dijkstra)算法过程 四.源码 一.应用场景-最 ...
- dij算法堆优化_迪杰斯特拉算法(Dijkstra) (基础dij+堆优化) BY:优少
算法实现步骤: a.初始时,只包括源点,即S = {v},v的距离为0.U包含除v以外的其他顶点,即:U ={其余顶点},若v与U中顶点u有边,则(u,v)为正常权值,若u不是v的出边邻接点,则(u, ...
- dij算法堆优化_迪杰斯特拉算法(Dijkstra) (基础dij+堆优化) BY:优少(示例代码)...
算法实现步骤: a.初始时,只包括源点,即S = {v},v的距离为0.U包含除v以外的其他顶点,即:U ={其余顶点},若v与U中顶点u有边,则(u,v)为正常权值,若u不是v的出边邻接点,则(u, ...
- 图的最短路径--迪杰斯特拉算法 c语言
还是按照书上的例子: 完整代码如下: #include <stdio.h> #include <stdlib.h> #include <string.h> #def ...
- 最短路径迪杰斯特拉算法 c语言,Dijkstra第K最短路径算法
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 //运筹学之最短路径 #include #include #define M 99999 int main() { int G[100][100]; in ...
最新文章
- python进程执行带有参数的任务(args、kwargs)
- python 使用UUID库生成唯一ID
- java左移、右移、无符号右移
- 黑马程序员pink老师前端入门教程,零基础必看的JavaScript基础语法视频教程(DOM)
- 怎么从转移特性曲线上看dibl_「科普向」这篇让你快速搞懂IGBT的静态特性
- Python入门--列表,字典,元组,集合总结
- Idea和Eclipse快捷键对比
- 淘宝 卖家信用等级的图示
- mybatis与spring集成
- Unity基础案例讲解:创建小型太空射击游戏(四)
- python制作简单网页_怎么用python简单的制作一个网页
- 英文名字按首字母排序分类显示
- mac字体渲染精细处理
- OSPF的NBMA环境建立邻居及排错,理论+实战讲解,干货分享
- 10. JavaScript
- 注册服务号、订阅号流程
- 基于matlab的陷波滤波器设计
- 在2012年01月20号这一天,2345浏览器的V1.3版本出世了,又修复什么Bug?
- [SWPUCTF 2018]SimplePHP
- Proe无法保存DWG格式的问题