单愿最短路径描述:给定带权有向图G=(V,E),其中每条边的权是非负实数。另外,还给定V中的一个顶点,称之为源(origin)。如今要计算从源到其余各顶点的最短路径的长度。这里的路径长度指的是到达路径各边权值之和。算法
Dijkstra算法是解单源最短路径问题的贪心算法。Dijkstra算法的基本思想是:设置顶点集合S并不断地作贪心选择来扩充集合。一个顶点属于集合S当且仅当从源点到该顶点的最短路径长度已知。贪心扩充就是不断在集合S中添加新的元素(顶点)。
初始时,集合S中仅含有源(origin)一个元素。设curr是G的某个顶点,把从源到curr且中间只通过集合S中顶点的路称之为从源到顶点curr的特殊路径,而且使用数组distance记录当前每一个顶点所对应的最短路径的长度。Dijkstra算法每次从图G中的(V-S)的集合中选取具备最短路径的顶点curr,并将curr加入到集合S中,同时对数组distance进行必要的修改。一旦S包含了全部的V中元素,distance数组就记录了从源(origin)到其余顶点的最短路径长度。 c#
核心代码:
Dijkstra描述:带权有向图G=(V,E),V={1,2,3,...}。顶点origin是源。数组distance[index]表示当前源到顶点index的最短路径长度。数组prev[index]表示源点到达index顶点最短路径的前一个顶点[Dijkstra只能获取最短路径的长度,经过prev记录前驱顶点能够很方便的获取详细的最短路径]。
数据结构与代码:数组
public struct DIJGraph { public int[] vexs; public int[][] arcs; public int num; } public static bool DIJKSTRA(int origin,DIJGraph g,int[] distance,int[] prev) { if (origin < 0 || origin >= g.num) return false; bool[] s = new bool[g.num]; for (int index = 0; index < g.num; ++index) { s[index] = false; distance[index] = g.arcs[origin][index]; prev[index] = (distance[index] == Int32.MaxValue) ? -1 : origin; } distance[origin] = 0; s[origin] = true; for (int i = 0; i < g.num; ++i) { int temp = Int32.MaxValue; int curr = 0; for (int index = 0; index < g.num; ++index) { if (!s[index] && distance[index] < temp) { curr = index; temp = distance[index]; } } s[curr] = true; for (int index = 0; index < g.num; ++index) { if (!s[index] && g.arcs[curr][index] < Int32.MaxValue) { int newDistance = distance[curr] + g.arcs[curr][index]; if (newDistance < distance[index]) { distance[index] = newDistance; prev[index] = curr; } } } } return true; }
贪心选择性质|最优子结构性质是Dijkstra算法所具有的。不过,虽然Dijkstra算法是解决单源最短路径的一款很优秀的算法,可是若是在图中存在多条最短路径,Dijkstra算法只能获取路径的长度,而没法给出最短路径的详细状况。即便在代码中添加distance[index]表示当前源到顶点index的最短路径长度。数组prev[index]来记录前驱点,可是一旦存在多条最短路径,咱们只能获取最早遇到的那条(或者最后遇到的那条路径)[每每,咱们偏向于获取的是最短路线而非路长]。总之,Dijkstra算法还有许多改进的地方。
本文提供的核心代码使用C#实现,您能够点击下载获取源代码[点击下载C语言实现代码]。网络