标签:
迪杰斯特拉算法是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法。是从一个顶点到其余各顶点的最短路径算法,解决的是有向图中最短路径问题。迪杰斯特拉算法主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。
该算法复杂度为n^2
这里有一篇讲解的很清晰的文章:http://blog.chinaunix.net/uid-26548237-id-3834514.html
下面说说我个人的理解:
就以这张图为例:
要找出A点到其他点的最短路径,应该怎么找?
这个算法的思路是:
具体的实现如下:
1 #include <iostream> 2 using namespace std; 3 4 #define MAXVEX 20 5 #define MAXEDGE 20 6 #define INFINITY 65535 7 8 9 10 typedef struct 11 { 12 int vexs[MAXVEX]; 13 int arc[MAXVEX][MAXVEX]; 14 int numVertexes,numEdges; 15 }MGraph; 16 17 typedef int Patharc[MAXVEX]; 18 typedef int ShortPathTable[MAXVEX]; 19 20 void CreateGraph(MGraph* G) 21 { 22 cout<<"请输入边数和顶点数:\n"; 23 int d,n,i,j; 24 cin>>d>>n; 25 G->numVertexes = n; 26 G->numEdges = d; 27 28 //给顶点和边初始化 29 for(i = 0;i<G->numVertexes;i++) 30 G->vexs[i] = i; 31 for(i = 0;i<G->numVertexes;i++) 32 { 33 for(j = 0;j<G->numVertexes;j++) 34 { 35 if(i==j) 36 G->arc[i][j] = 0; 37 else 38 G->arc[i][j] = G->arc[j][i] = INFINITY; 39 } 40 } 41 42 G->arc[0][1]=1; 43 G->arc[0][2]=5; 44 G->arc[1][2]=3; 45 G->arc[1][3]=7; 46 G->arc[1][4]=5; 47 48 G->arc[2][4]=1; 49 G->arc[2][5]=7; 50 G->arc[3][4]=2; 51 G->arc[3][6]=3; 52 G->arc[4][5]=3; 53 54 G->arc[4][6]=6; 55 G->arc[4][7]=9; 56 G->arc[5][7]=5; 57 G->arc[6][7]=2; 58 G->arc[6][8]=7; 59 60 G->arc[7][8]=4; 61 62 for(i = 0;i<G->numVertexes;i++) 63 { 64 for(j = i;j<G->numVertexes;j++) 65 { 66 G->arc[j][i] = G->arc[i][j]; 67 } 68 } 69 } 70 71 /* Floyd算法,求网图G中各顶点v到其余顶点w的最短路径P[v][w]及带权长度D[v][w]。 */ 72 void Dijkstra(MGraph G,int v0, Patharc *P, ShortPathTable *D) 73 { 74 int v,w,k,min; 75 76 int final[MAXVEX];/* final[w]=1表示求得顶点v0至vw的最短路径 */ 77 78 for(v = 0;v<G.numVertexes;v++) 79 { 80 (*P)[v] = 0; 81 /* 初始化P */ 82 (*D)[v] = G.arc[v0][v]; 83 /* D[v]值即为对应点间的权值 */ 84 final[v] = 0; 85 } 86 87 (*D)[v0] = 0; 88 final[v0] = 1; 89 90 /* 开始主循环,每次求得v0到某个v顶点的最短路径 */ 91 for(v = 1;v<G.numVertexes;v++) 92 { 93 min = INFINITY;/* 当前所知离v0顶点的最近距离 */ 94 for(w = 0;w<G.numVertexes;w++)/* 寻找离v0最近的顶点 */ 95 { 96 if((*D)[w]<min && !final[w]) 97 { 98 min = (*D)[w]; /* w顶点离v0顶点更近 */ 99 k = w; 100 } 101 final[k] = 1; /* 将目前找到的最近的顶点置为1 */ 102 } 103 104 /* 修正当前最短路径及距离 */ 105 for(w = 0;w<G.numVertexes;w++)/* 寻找离v0最近的顶点 */ 106 { 107 /* 如果经过v顶点的路径比现在这条路径的长度短的话 */ 108 if(min+G.arc[k][w] < (*D)[w] && !final[w]) 109 { 110 /* 说明找到了更短的路径,修改D[w]和P[w] */ 111 (*D)[w] = min+G.arc[k][w]; 112 (*P)[w] = k; 113 } 114 } 115 } 116 117 } 118 119 120 int main() 121 { 122 int v0,i,j; 123 124 MGraph G; 125 126 Patharc P; 127 ShortPathTable D; 128 129 CreateGraph(&G); 130 v0 = 0; 131 Dijkstra(G,v0,&P,&D); 132 133 cout<<"最短路径倒序如下:\n"; 134 for(i = 1;i<G.numVertexes;i++) 135 { 136 cout<<"v0 - v"<<i<<" : "; 137 j = i; 138 while(P[j]!=0) 139 { 140 cout<<P[j]<<" "; 141 j = P[j]; 142 } 143 cout<<endl; 144 } 145 146 cout<<"\n源点到各顶点的最短路径长度为:\n"; 147 148 for(i=1; i<G.numVertexes; ++i) 149 { 150 cout<<"v"<<G.vexs[0]<<" - v"<<G.vexs[i]<<" : "<<D[i]<<endl; 151 } 152 return 0; 153 154 155 }
算法优化:
参考这篇文章:http://blog.csdn.net/zhongyanghu27/article/details/8221276
该算法复杂度为n^2,我们可以发现,如果边数远小于n^2,对此可以考虑用堆这种数据结构进行优化,取出最短路径的复杂度降为O(1);每次调整的复杂度降为O(elogn);e为该点的边数,所以复杂度降为O((m+n)logn)。
A*算法优化策略
问题:Dijkstra算法基于广度优先搜索策略,即从源点出发,通过权值迭代遍历所有其他结点后,最后得到从源点到其他各结点的最短路径。整个搜索好似一个圆形向外展开,直到到达目的地,这样的搜索方式是盲目的。很明显这样求解一定能找到最优解,但节点展开的数量和距离成级数增加,会导致大量无效点的搜索,大大的降低搜索的效率。
优化策略:采用改进的Dijkstra算法——A*算法。A*算法是人工智能运用在游戏中的一个重要实践,它主要是解决路径搜索问题。A*算法实际是一种启发式搜索。发表论文。所谓启发式搜索,就是利用一个估价函数judge()评估每次决策的价值,决定先尝试哪一种方案。这样可以极大地优化普通的广度优先搜索。从Dijkstra算法到A*算法是判断准则的引入,如果这个判断条件不成立,同样地,只能采用Dijkstra算法。所以A*算法中的估价函数是至关重要[3]。
扇形优化策略
问题:Dijkstra算法的搜索过程好似以源点为圆心的一系列同心圆向外展开,搜索过程中没有考虑到终点所在方向或位置,搜索是盲目的。这样导致大量的无用临时结点被反复搜索,成为实际应用中的瓶颈。
优化策略:从尽量减少最短路径分析过程中搜索的临时结点数量,限制范围搜索和限定方向搜索考虑进行优化。那么这种有损算法是否可行呢?我们知道,现实生活中行进,不会向着目的地的相反方向行进,否则就是南辕北辙。所以,当所研究的网络可以抽象化为平面网络的条件下,也不必搜索全部结点,可以在以源点到终点所在直线为轴线的扇形区域内搜索最短路径。这样,搜索方向明显地趋向终点,提高了搜索速度,虽然抛弃了部分结点,但基本上不影响搜索的成功率[5]。
邻接点优化策略
问题:Dijkstra算法在提取最短路径结点时需要访问所有的未确定最短路径的结点,算法的时间复杂度为O(n2),如果只希望找到从源点到某一特定的终点的最短路径也不例外。结点数n越大,算法的计算效率和存储效率越低。
优化策略:只对最短路径上结点的邻接点作处理,不涉及其他结点。即(1)只从源点的邻接点集合中选择权值最小的结点作为转接点,将此转接点加入已确定最短路径的结点集合S中;(2)对此转接点的邻接点集合与S的差集中的结点的权值进行更新;(3)从S中所有结点的邻接点集合的并集与S的差集中选择权值最小的结点作为下一个转接点,并将此转接点加入S中。重复(2),(3)操作,直至所有的结点确定最短路径。优化算法在更新最短路径值与选择最短路径值最小的结点时,仅仅涉及相关结点的邻接点集合及S集合中所有结点的邻接点集合与S集合的差集,时间复杂度取决于转接点的邻接点的数量多少,减少了计算次数与比较次数
参考文献:
[1] 严蔚敏,吴伟民. 数据结构(C语言版)[M]. 北京:清华大学出版社,1997,186~190.
[2] 谢柏青,佘晓歌. 算法与数据结构[M]. 北京:高等教育出版社,2001,230~232.
[3] 陈益富,卢 潇,丁豪杰. 对Dijkstra算法的优化策略研究[J]. 计算机技术与发展,2006,16(9):73~75.
[4] 章永龙. Dijkstra最短路径算法优化[J]. 南昌工程学院学报,2006,25(3):30~33.
[5] 胡树玮,张修如,赵 洋.扇形优化Dijkstra算法[J]. 计算机技术与发展,2006,16(12):49~51.
标签:
原文地址:http://www.cnblogs.com/qlky/p/4966402.html