今天学了下数据结构,最近国旗班最后一周训练着实使我没什么时间写博客,这也算是挤出点时间把迪杰斯特拉算法好好整了整,我尽量把这个清晰的写出来。这里也参考大佬的代码让我对程序大体有了思路,也算是站在巨人的肩膀上吧。

Dijkstra算法(C语言)

  • Dijkstra算法
  • 题目
  • 代码

Dijkstra算法

(本质就是贪心)

迪杰斯特拉算法是由荷兰计算机科学家狄克斯特拉于1959年提出
,是从一个顶点到其余各顶点的最短路径算法,解决的是有权图中
最短路径问题。
迪杰斯特拉算法的主要特点是以起始点为中心向外层层扩展(广度
优先搜索思想),直到扩展到终点为止。迪杰斯特拉算法的成功率是最高的,因为它每次必能搜索到最优路径。
但迪杰斯特拉算法算法的搜索速度是最慢的。迪杰斯特拉算法求一个点
到其他所有点的最短路径时间复杂度为 O ( n 2 )

我这里比较喜欢《小灰的奇妙算法》这本书,感觉比较易懂(啃算法导论的大佬请无视----)这里就把图放在这里了,挺不错的。
步骤如下:

究竟什么是迪杰斯特拉算法?它是如何寻找图中顶点的最短路径呢?这个算法的本质,是不断刷新起点与其他各个顶点之间的 “距离表”。让我们来演示一下迪杰斯特拉的详细过程:第1步,创建距离表。表中的Key是顶点名称,Value是从起点A
到对应顶点的已知最短距离。但是,一开始我们并不知道A到其他
顶点的最短距离是多少,Value默认是无限大:

第2步,遍历起点A,找到起点A的邻接顶点B和C。
从A到B的距离是5,从A到C的距离是2。把这一信息刷新到距离表当中:

第3步,从距离表中找到从A出发距离最短的点,也就是顶点C。第4步,遍历顶点C,找到顶点C的邻接顶点D和F(A已经遍历过,
不需要考虑)。从C到D的距离是6,所以A到D的距离是2+6=8;
从C到F的距离是8,所以从A到F的距离是2+8=10。把这一信息
刷新到表中:

接下来重复第3步、第4步所做的操作:第5步,也就是第3步的重复,从距离表中找到从A出发距离最短的点(
C已经遍历过,不需要考虑),也就是顶点B。第6步,也就是第4步的重复,遍历顶点B,找到顶点B的邻接顶点D和E
(A已经遍历过,不需要考虑)。从B到D的距离是1,所以A到D的距离是
5+1=6,小于距离表中的8;从B到E的距离是6,所以从A到E的距离是5+6=11。
把这一信息刷新到表中:

(在第6步,A到D的距离从8刷新到6,可以看出距离表所发挥的作用。
距离表通过迭代刷新,用新路径长度取代旧路径长度,最终可以得到从
起点到其他顶点的最短距离)第7步,从距离表中找到从A出发距离最短的点(B和C不用考虑),也就是顶点D。第8步,遍历顶点D,找到顶点D的邻接顶点E和F。从D到E的距离是1,
所以A到E的距离是6+1=7,小于距离表中的11;从D到F的距离是2,
所以从A到F的距离是6+2=8,小于距离表中的10。把这一信息刷新到表中:

第9步,从距离表中找到从A出发距离最短的点,也就是顶点E。第10步,遍历顶点E,找到顶点E的邻接顶点G。从E到G的距离是7,
所以A到G的距离是7+7=14。把这一信息刷新到表中:

第11步,从距离表中找到从A出发距离最短的点,也就是顶点F。第10步,遍历顶点F,找到顶点F的邻接顶点G。从F到G的距离是3,
所以A到G的距离是8+3=11,小于距离表中的14。把这一信息刷新到表中:

就这样,除终点以外的全部顶点都已经遍历完毕,距离表中存储的是从
起点A到所有顶点的最短距离。显然,从A到G的最短距离是11。(路径:A-B-D-F-G)

题目

代码

#include <stdio.h>
#include <stdlib.h>
#define MAX 100
//定义一个结点
//边表
struct edgeNode
{int headVex;//相邻顶点字段int weight;//权重struct edgeNode *next;//链字段
};
//定义一个头节点
//顶点表
struct vexNode
{int vex;//顶点信息struct edgeNode *head;//边表头指针
};
//定义图
struct graphList
{struct vexNode vex[MAX];int vexNum;//顶点数int edgeNum;//边个数
};struct step{int flags[1000];int stepN[1000];
};//函数申明防止报warning
void run ();
void createNewGraphList (struct graphList *gList);
void clearVexNodes (struct graphList *gList);
void createNewEdgeNode (int n,struct graphList *gList);
void Dikstra(struct step *S,struct graphList *gList);
void clearStep(struct step *S,struct graphList *gList);
void initializeStep(struct step *S,struct graphList *gList);
int judgeStep(struct step *S,struct graphList *gList);
int findMinStepN(struct step *S,struct graphList *gList);
void updateStepN(struct step *S,struct graphList *gList,int min);
void print(struct step *S,struct graphList *gList);
void swap(int *a,int *b);
void quicksort(int array1[],int array2[],int maxlen,int begin,int end);void createNewGraphList (struct graphList *gList)//创建图
{scanf ("%d%d",&(gList->vexNum),&(gList->edgeNum));clearVexNodes (gList);//注意此处不加&int i,vex;for (i=0;i<gList->edgeNum;i++)//添加结点{scanf ("%d",&vex);gList->vex[vex-1].vex=vex;createNewEdgeNode (vex-1,gList);//新建结点}
}
void createNewEdgeNode (int n,struct graphList *gList)//新建结点
{struct edgeNode *p,*q;int headVex;p=(struct edgeNode *)malloc(sizeof(struct edgeNode));scanf ("%d",&headVex);//输入尾p->headVex=headVex-1;//逐一此处,因为我们以0为边表第一个位置,所以要-1scanf ("%d",&(p->weight));//输入权重p->next=NULL;//此用尾插if (gList->vex[n].head==NULL)//若边表本来无元素{gList->vex[n].head=p;}else//边表有元素,将操作位置移动到此边表尾部{q=gList->vex[n].head;while (q->next){q=q->next;}q->next=p;//尾插}
}void clearVexNodes (struct graphList *gList)//图的初始化
{int i;for (i=0;i<gList->vexNum;i++){gList->vex[i].vex=0;//边表信息设为0gList->vex[i].head=NULL;//边表结点设为NULL}
}void Dijkstra(struct step *S,struct graphList *gList)//算法主体
{int min;clearStep (S,gList);//初始化,即清空步数initializeStep (S,gList);//初始化while (judgeStep (S,gList))//判断步骤{min=findMinStepN (S,gList);//找最小步updateStepN (S,gList,min);//更新步数}
}
void clearStep(struct step *S,struct graphList *gList)//初始化,即清空步数
{int i;for (i=0;i<gList->vexNum;i++){S->flags[i]=-1;//-1无路,0以找到最短路径,1未找到最短路径S->stepN[i]=0;//到此节点的步数为0}
}void initializeStep(struct step *S,struct graphList *gList)//初始化,即把首元素放进循环开始判断
{struct edgeNode *p;p=gList->vex[0].head;while (p)//循环边表{S->flags[p->headVex]=1;//设置为未找到最短路径S->stepN[p->headVex]=p->weight;//设置到此节点步数p=p->next;}
}int judgeStep(struct step *S,struct graphList *gList)//判断步骤(要使所有元素都进行循环并处理找到最小步数)
{int i;for (i=1;i<gList->vexNum;i++)//循环所有节点{if (S->flags[i]==1)//若有节点被设为未找到最短路径{return 1;//返回1,继续循环}}return 0;//返回0,结束循环
}int findMinStepN(struct step *S,struct graphList *gList)//找最小步(找这次循环要处理的元素)
{int i,min=99999,n=-1;for (i=1;i<gList->vexNum;i++)//循环所有节点{if (S->flags[i]==1)//若被设为未找到最短路径{if (S->stepN[i]<min)//若比已知最小小,就替换{min=S->stepN[i];n=i;}}}return n;//返回得到的最小步数的节点的编号
}void updateStepN(struct step *S,struct graphList *gList,int min)//更新步数
{struct edgeNode *p;int minStepN=S->stepN[min];p=gList->vex[min].head;S->flags[min]=0;//将此次循环的元素列为处理过的,以后的循环就不再处理它)while (p)//循环边表(循环要此次处理的元素){if (S->flags[p->headVex]==1)//若未找到最短路径(即还未处理过,我们知道进入循环,处理过的元素必定是找到最小路径的){if (p->weight+minStepN<S->stepN[p->headVex])//若新的走法的步数较少{S->stepN[p->headVex]=p->weight+minStepN;//就更新到此节点的步数}}else{if (S->flags[p->headVex]==-1)//若此节点无路到达{S->flags[p->headVex]=1;//放到下次循环里S->stepN[p->headVex]=p->weight+minStepN;//新的走法有路到达,更新其步数}}p=p->next;}
}void print(struct step *S,struct graphList *gList)//输出步骤
{int i;int nList[3000]={0};//步数int noList[3000]={0};//节点编号for (i=1;i<gList->vexNum;i++){if (S->flags[i]==-1)//若无路到达,步数就是-1{nList[i]=-1;}else{nList[i]=S->stepN[gList->vex[i].vex-1];//否则就是步数}noList[i]=i+1;//节点编号赋值}quicksort (nList,noList,gList->vexNum,1,gList->vexNum-1);//将步数从小到大排,编号随之改变for (i=1;i<gList->vexNum;i++){if (nList[i]>0)//先输出有路到达的{printf ("1 %d %d\n",noList[i],nList[i]);}}for (i=1;i<gList->vexNum;i++){if (nList[i]==-1)//再输出无路到达的{printf ("1 %d %d\n",noList[i],nList[i]);}}
}
void swap(int *a,int *b)//交换数值
{int temp;temp=*a;*a=*b;*b=temp;
}void quicksort(int array1[],int array2[],int maxlen,int begin,int end)//以array1排序,同时改变array2
{int i,j;if(begin<end){i=begin + 1;j=end;while(i<j){if(array1[i]>array1[begin]){swap(&array1[i],&array1[j]);swap(&array2[i],&array2[j]);j--;}else{i++;}}if(array1[i]>=array1[begin]){i--;}swap(&array1[begin],&array1[i]);swap(&array2[begin],&array2[i]);quicksort(array1,array2,maxlen,begin,i);quicksort(array1,array2,maxlen,j,end);}
}int main()
{struct graphList gList;struct step S;createNewGraphList(&gList);Dijkstra(&S,&gList);print (&S,&gList);}

结果:

Dijkstra(迪杰斯特拉)算法(C语言)相关推荐

  1. 狄斯奎诺算法 c语言,图的邻接表实现迪杰斯特拉算法(C语言).doc

    图的邻接表实现迪杰斯特拉算法(C语言) /*迪杰斯特拉算法(狄斯奎诺算法)解决的是从源点到其它所有顶点的最短路径问题*/ //算法实现: #include #include #define MAX 2 ...

  2. 狄斯奎诺算法 c语言,图的邻接表实现迪杰斯特拉算法(C语言)

    图的邻接表实现迪杰斯特拉算法(C语言). 迪杰斯特拉算法(狄斯奎诺算法)解决的是从源点到其它所有顶点的最短路径问题. 图的邻接表实现迪杰斯特拉算法(C语言) /*迪杰斯特拉算法(狄斯奎诺算法)解决的是 ...

  3. Dijkstra(迪杰斯特拉)算法求单源最短路径问题

    Dijkstra(迪杰斯特拉)算法求单源最短路径问题 重要的事情说三遍:代码不是我写的!代码不是我写的!代码不是我写的! 第一个算法是严蔚敏数据结构(C语言版)上写的,第二个算法是王道数据结构上写的, ...

  4. JavaScript实现dijkstra迪杰斯特拉算法(附完整源码)

    JavaScript实现dijkstra迪杰斯特拉算法 PriorityQueue完整源代码 MinHeap.js完整源代码 Heap.js完整源代码 Comparator.js完整源代码 dijks ...

  5. C++实现Dijkstra(迪杰斯特拉)算法(附完整源码)

    C++Dijkstra迪杰斯特拉算法的实现 C++Dijkstra(迪杰斯特拉)算法的完整源码(定义,实现,main函数测试) C++Dijkstra(迪杰斯特拉)算法的完整源码(定义,实现,main ...

  6. Dijkstra迪杰斯特拉算法 C++实现

    本篇文章主要介绍了Dijkstra迪杰斯特拉算法的C++实现,文章包含两个部分,在第一部分中我会简单介绍迪杰斯特拉算法以及一些个人的理解,第二部分会对C++代码的逻辑进行解释.下面是我已经上传的代码资 ...

  7. 最短路径之Dijkstra(迪杰斯特拉)算法(无向图)

    简介      Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.由for循环可知,其时间 ...

  8. MATLAB轻松绘制地图路线——Dijkstra(迪杰斯特拉)算法最短路径规划

    文章目录 1. 地图绘制 2. 计算各节点之间的距离 3. Dijkstra(迪杰斯特拉)算法 4. 根据计算出的距离利用Dijkstra(迪杰斯特拉)算法找出指定节点之间的最短路径 工程文件(可直接 ...

  9. C语言实现Dijkstra(迪杰斯特拉)算法(附完整源码)

    Dijkstra迪杰斯特拉 Graph结构体定义 迪杰斯特拉算法完整源码(定义,实现,main函数测试) Graph结构体定义 struct Graph {int vertexNum;int **ed ...

  10. 迪杰斯特拉算法c语言要点,C语言迪杰斯特拉实现最短路径算法要点.doc

    C语言迪杰斯特拉实现最短路径算法要点.doc 数据结构课程设计报告 ----旅游咨询系统设计 目录 一.需求分析- 2 - 二.系统分析- 2 - 三.概要设计- 3 - 一.系统划分- 3 - 二. ...

最新文章

  1. 高效搭建Storm全然分布式集群
  2. LeetCode Remove Linked List Elements
  3. [机器学习] 训练集(train set) 验证集(validation set) 测试集(test set)
  4. 第二十篇:定义一个整形变量
  5. Mysql 死锁过程及案例详解之元数据锁MetaData Lock
  6. Java程序员需要掌握的计算机底层知识(二):操作系统、内核、用户态与内核态、系统调用的执行过程
  7. EF Code First学习笔记:数据库创建(转)
  8. linux 内核编译安装及卸载
  9. 读取和修改caffemodel文件里的参数
  10. 时区日期处理及定时 (NSDate,NSCalendar,NSTimer,NSTimeZone) -- IOS(实例)
  11. 【学习笔记】APP测试基本流程及测试要点
  12. EPSnbsp;QOS体系图的解读
  13. 佳能打印机清零操作及清零软件
  14. 绘制正方形图形(C语言)
  15. 宠物商店业务逻辑关系模型图
  16. 语义分割 语义分类_路面语义分割
  17. MATLAB以符号形式表示门函数的傅里叶正反变换。
  18. 未找到导入的项目“C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\VC\VCT
  19. SEER数据库中肿瘤发病率计算并绘制发病率趋势图
  20. 【数据可视化】复杂高维多元数据的可视化

热门文章

  1. 操作无法完成。键入的打印机名不正确,或者指定的打印机没有连接到服务器上...
  2. What’s The Difference Between A Codec, Container And Video Format?
  3. 《心静的力量》读书笔记
  4. 二、同步mysql数据库
  5. Excel必知必会——迷你图
  6. vn.py源码解读(一、环境配置与回测初试)
  7. vue 画一个小圆点
  8. ES5 —— reduce 方法
  9. 灵活例子彻底搞懂reduce
  10. 小学计算机教学管理工作总结,2020小学信息技术教师教学工作总结