Dijkstra算法
来源:互联网 发布:ios 数据库开发 编辑:程序博客网 时间:2024/06/10 08:42
========================================================================
这主要是用来找起点与终点最短路径的方法,搜索是以目标节点全遍历的方式进行搜索,一步步确定每个节点的最短路径才终止.
操作过程中分两集合: 确定最短路径顶点集合U 与 未确定最短路径顶点集合V. 利用U里面的有向向量链分别搜索V里面的每个节点,形成的最短链对应的那个节点就可以确定最短路径了,其就可以加入集合U,逐步搜索整个集合V,直到V中数量减小到零,全部确定.
========================================================================
先上基本搜索步骤图对算法理解.转自:图之Dijkstra算法
图之Dijkstra算法
Dijkstra算法是一种求单源最短路的算法,即从一个点开始到所有其他点的最短路。其步骤如下: (原文链接有参考代码.)
1
2
3
4
5
6
既然理解了搜索步骤,那我们看看其中的思想. 参见:最短路径之Dijkstra算法详细讲解
最短路径之Dijkstra算法详细讲解
1 最短路径算法
在日常生活中,我们如果需要常常往返A地区和B地区之间,我们最希望知道的可能是从A地区到B地区间的众多路径中,那一条路径的路途最短。最短路径问题是图论研究中的一个经典算法问题, 旨在寻找图(由结点和路径组成的)中两结点之间的最短路径。 算法具体的形式包括:
(1)确定起点的最短路径问题:即已知起始结点,求最短路径的问题。
(2)确定终点的最短路径问题:与确定起点的问题相反,该问题是已知终结结点,求最短路径的问题。在无向图中该问题与确定起点的问题完全等同,在有向图中该问题等同于把所有路径方向反转的确定起点的问题。
(3)确定起点终点的最短路径问题:即已知起点和终点,求两结点之间的最短路径。
(4)全局最短路径问题:求图中所有的最短路径。
用于解决最短路径问题的算法被称做“最短路径算法”, 有时被简称作“路径算法”。 最常用的路径算法有:Dijkstra算法、A*算法、Bellman-Ford算法、Floyd-Warshall算法、Johnson算法。
2 Dijkstra算法
2.1 Dijkstra算法
Dijkstra算法是典型最短路算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。Dijkstra算法能得出最短路径的最优解,但由于它遍历计算的节点很多,所以效率低。
Dijkstra算法是很有代表性的最短路算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹学等等。
2.2 Dijkstra算法思想
Dijkstra算法思想为:
设G=(V,E)是一个带权有向图,把图中顶点集合V分成两组,
第一组为已求出最短路径的顶点集合(用S表示,初始时S中只有一个源点,以后每求得一条最短路径 , 就将 加入到集合S中,直到全部顶点都加入到S中,算法就结束了),
第二组为其余未确定最短路径的顶点集合(用U表示),按最短路径长度的递增次序依次把第二组的顶点加入S中。在加入的过程中,总保持从源点v到S中各顶点的最短路径长度不大于从源点v到U中任何顶点的最短路径长度。
此外,每个顶点对应一个距离,S中的顶点的距离就是从v到此顶点的最短路径长度,U中的顶点的距离,是从v到此顶点只包括S中的顶点为中间顶点的当前最短路径长度。
2.3 Dijkstra算法具体步骤
(1)初始时,S只包含源点,即S=,v的距离为0。U包含除v外的其他顶点,U中顶点u距离为边上的权(若v与u有边)或 )(若u不是v的出边邻接点)。
(2)从U中选取一个距离v最小的顶点k,把k,加入S中(该选定的距离就是v到k的最短路径长度)。
(3)以k为新考虑的中间点,修改U中各顶点的距离;若从源点v到顶点u(u U)的距离(经过顶点k)比原来距离(不经过顶点k)短,则修改顶点u的距离值,修改后的距离值的顶点k的距离加上边上的权。
(4)重复步骤(2)和(3)直到所有顶点都包含在S中。
2.4 Dijkstra算法举例说明
如下图,设A为源点,求A到其他各顶点(B、C、D、E、F)的最短路径。线上所标注为相邻线段之间的距离,即权值。(注:此图为随意所画,其相邻顶点间的距离与图中的目视长度不能一一对等)
图一:Dijkstra无向图
算法执行步骤如下表:【注:图片要是看不到请到“相册--日志相册”中,名为“Dijkstra算法过程”的图就是了】
========================= 转自最短路径之Dijkstra算法 =========================
dijkstra算法两个应用题:
HDOJ 1874 畅通工程续,现有解法:www.wutianqi.com/?p=1894
HDOJ 2544 最短路,现有解法:www.wutianqi.com/?p=1892
参考:http://hi.baidu.com/zealot886/item/c8a499ee5795bcddeb34c950
数据结构(C语言版)
http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html
推荐几篇搜索算法相关的非常好的博文:
一、A*搜索算法
一(续)、A*,Dijkstra,BFS算法性能比较及A*算法的应用
二、Dijkstra 算法初探 (Dijkstra算法系列4篇文章)
二(续)、彻底理解Dijkstra算法
二(再续)、Dijkstra 算法+fibonacci堆的逐步c实现
二(三续)、Dijkstra 算法+Heap堆的完整c实现源码
==============
代码
#include <stdio.h>#include <malloc.h>#define VERTEXNUM 6//存放最短路径的边元素typedef struct edge{ int vertex; int value; struct edge* next;}st_edge;void createGraph(int (*edge)[VERTEXNUM], int start, int end, int value);void displayGraph(int (*edge)[VERTEXNUM]);void displayPath(st_edge** path, int startVertex,int* shortestPath);void dijkstra(int (*edge)[VERTEXNUM], st_edge*** path, int** shortestPath, int startVertex, int* vertexStatusArr);int getDistance(int value, int startVertex, int start, int* shortestPath);void createPath(st_edge **path, int startVertex, int start, int end, int edgeValue);int main(void){ //动态创建存放边的二维数组 int (*edge)[VERTEXNUM] = (int (*)[VERTEXNUM])malloc(sizeof(int)*VERTEXNUM*VERTEXNUM); int i,j; for(i=0;i<VERTEXNUM;i++){ for(j=0;j<VERTEXNUM;j++){ edge[i][j] = 0; } } //存放顶点的遍历状态,0:未遍历,1:已遍历 int* vertexStatusArr = (int*)malloc(sizeof(int)*VERTEXNUM); for(i=0;i<VERTEXNUM;i++){ vertexStatusArr[i] = 0; } printf("after init:\n"); displayGraph(edge); //创建图 createGraph(edge,0,1,6); createGraph(edge,0,3,5); createGraph(edge,0,2,1); createGraph(edge,1,2,5); createGraph(edge,1,4,3); createGraph(edge,2,4,6); createGraph(edge,2,3,5); createGraph(edge,2,5,4); createGraph(edge,3,5,2); createGraph(edge,4,5,6); printf("after create:\n"); displayGraph(edge); //最短路径 /*存储的结构如下: path[0]:edge0->NULL path[1]:edge1->NULL path[2]:edge1->edge2->NULL path[3]:edge1->edge2->edge3->NULL path[4]:edge4->NULL 从顶点0到0的最短路径:从0出发直接到0 从顶点0到1的最短路径:从0出发直接到1 从顶点0到2的最短路径:从0出发到1,从1出发到2 ...... */ st_edge** path = NULL; //存储最短路径的权值 /* shortestPath[0] = 0; shortestPath[1] = 8; shortestPath[2] = 12; 从顶点0到0的路径是0 从顶点0到1的路径是8 从顶点0到2的路径是12 */ int* shortestPath = NULL; //从顶点0开始寻找最短路径 int startVertex = 0; //最短路径 dijkstra(edge, &path, &shortestPath, startVertex, vertexStatusArr); printf("the path is:\n"); displayPath(path,startVertex,shortestPath); free(edge); free(path); return 0;}//创建图void createGraph(int (*edge)[VERTEXNUM], int start, int end, int value){ edge[start][end] = value; edge[end][start] = value;}//打印存储的图void displayGraph(int (*edge)[VERTEXNUM]){ int i,j; for(i=0;i<VERTEXNUM;i++){ for(j=0;j<VERTEXNUM;j++){ printf("%d ",edge[i][j]); } printf("\n"); }}//打印最短路径void displayPath(st_edge** path, int startVertex,int* shortestPath){ int i; st_edge* p; for(i=0;i<VERTEXNUM;i++){ printf("Path from %d to %d:",startVertex,i); p = *(path+i); while(p != NULL){ printf("%d(%d) ",p->vertex,p->value); p = p->next; } printf("\n"); printf("the count is:%d\n",shortestPath[i]); }}//最短路径void dijkstra(int (*edge)[VERTEXNUM], st_edge*** path, int** shortestPath, int startVertex, int* vertexStatusArr){ //初始化最短路径 *path = (st_edge**)malloc(sizeof(st_edge*)*VERTEXNUM); int i,j; for(i=0;i<VERTEXNUM;i++){ if(i == startVertex){ st_edge* e = (st_edge*)malloc(sizeof(st_edge)); e->vertex = startVertex; e->value = 0; e->next = NULL; (*path)[i] = e; }else{ (*path)[i] = NULL; } } //初始化最短路径的权值 *shortestPath = (int *)malloc(sizeof(int)*VERTEXNUM); for(i=0;i<VERTEXNUM;i++){ if(i == startVertex){ (*shortestPath)[i] = 0; }else{ (*shortestPath)[i] = -1; } } //从顶点0开始,则顶点0就是已访问的 vertexStatusArr[startVertex] = 1; int shortest, distance,start, end, edgeValue, vNum = 1; //如果还顶点还没有访问完 while(vNum < VERTEXNUM){ shortest = 9999; for(i=0;i<VERTEXNUM;i++){ //选择已经访问过的点 if(vertexStatusArr[i] == 1){ for(j=0;j<VERTEXNUM;j++){ //选择一个没有访问过的点 if(vertexStatusArr[j] == 0){ //选出一条value最小的边 if(edge[i][j] != 0 && (distance = getDistance(edge[i][j], startVertex, i, *shortestPath)) < shortest){ shortest = distance; edgeValue = edge[i][j]; start = i; end = j; } } } } } vNum++; //将点设置为访问过 vertexStatusArr[end] = 1; //保存最短路径权值 (*shortestPath)[end] = shortest; //保存最短路径 createPath(*path, startVertex, start, end, edgeValue); }}//返回从startVertex到新的顶点的距离int getDistance(int value, int startVertex, int start, int* shortestPath){ if(start == startVertex){ return value; }else{ return shortestPath[start] + value; }}//保存最短路径void createPath(st_edge **path, int startVertex, int start, int end, int edgeValue){ if(start == startVertex){ st_edge* newEdge = (st_edge*)malloc(sizeof(st_edge)); newEdge->vertex = end; newEdge->value = edgeValue; newEdge->next = NULL; st_edge** p = path + end; while((*p) != NULL){ p = &((*p)->next); } *p = newEdge; }else{ st_edge** pCopySrc = path + start; st_edge** pCopyDes = path + end; st_edge* newEdge = NULL; while((*pCopySrc) != NULL){ newEdge = (st_edge*)malloc(sizeof(st_edge)); *newEdge = **pCopySrc; newEdge->next = NULL; *pCopyDes = newEdge; pCopySrc = &((*pCopySrc)->next); pCopyDes = &((*pCopyDes)->next); } newEdge = (st_edge*)malloc(sizeof(st_edge)); newEdge->vertex = end; newEdge->value = edgeValue; newEdge->next = NULL; *pCopyDes = newEdge; }}
- Dijkstra算法
- dijkstra算法
- Dijkstra算法
- Dijkstra算法
- Dijkstra算法
- Dijkstra算法
- Dijkstra 算法
- Dijkstra算法
- Dijkstra算法
- Dijkstra算法
- Dijkstra 算法
- Dijkstra 算法
- dijkstra算法
- Dijkstra 算法
- Dijkstra算法
- Dijkstra算法
- Dijkstra算法
- dijkstra算法
- 三星Galaxy Tab S2上市,压制苹果之心凸显
- 你知道用AngularJs怎么定义指令吗?
- 备考SharePoint 2010 Certification (70-668)心得
- hdoj 1213 How Many Tables【并查集】
- 06-图6. 公路村村通(30)--最小生成树-prime-kruskal
- Dijkstra算法
- CAP定理小议
- 如何判断一个数的二进制有多少个1
- 【最短路】【负圈可达点】【用while(!Q.empty())】【优先队列优化】【dij】
- PAT 1063. Set Similarity (25)
- Caliburn Micro Part 3: More About Events and Parameters
- 线段树的一系列应用
- Think in Java之构造器的真正调用顺序
- webService之hello级别中的注意事项