1.定义概念
Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。值得注意的是,该算法要求图中不存在负权边.
2.基本思想
设置顶点集合S,初始时,S中仅含有起始点,把从起始点到u且中间只经过S中顶点的路称为从起始点到u的特殊路径,并用数组dist记录当前每个顶点所对应的最短特殊路径的长度.Dijkstra算法每次从S外取出对应dist值最小的节点u,将其添加到S中,并对所有与u点直接相连的点重新计算dist值,若变小,则修改.一旦S中包含了所有的顶点,则dist中就记录了从起始点到所有其它顶点的最短路径长度.
例如,对下图中的有向图,应用Dijkstra算法计算从源顶点1到其它顶点间最短路径的过程列在下表中。
Dijkstra算法的迭代过程:
迭代 |
s |
u |
dist[2] |
dist[3] |
dist[4] |
dist[5] |
初始 |
{1} |
- |
10 |
maxint |
30 |
100 |
1 |
{1,2} |
2 |
10 |
60 |
30 |
100 |
2 |
{1,2,4} |
4 |
10 |
50 |
30 |
90 |
3 |
{1,2,4,3} |
3 |
10 |
50 |
30 |
60 |
4 |
{1,2,4,3,5} |
5 |
10 |
50 |
30 |
60 |
3.代码实现:
1 using System; 2 using System.Collections.Generic; 3 4 5 namespace 动态规划 6 { 7 internal class Graphic 8 { 9 public List<Node> Nodes; 10 11 12 public int[] Dijkstra() 13 { 14 //1.一个集合S记录了所有的找到最短路径的数据 15 var S = new List<Node>(); 16 //2.一个数组dist记录了所有点当前的最短路径 17 var dist = new int[Nodes.Count]; 18 for (int i = 0; i < dist.Length; i++) 19 { 20 dist[i] = int.MaxValue; 21 } 22 //3.先加进去起点 23 var curNode = Nodes[0]; 24 dist[0] = 0; 25 S.Add(curNode); 26 27 while (true) 28 { 29 //当前节点没有边,则应该结束了把? 30 if (curNode.Edges == null || curNode.Edges.Count == 0) 31 break; 32 33 //遍历当前节点直接相连的点,更新dist值 34 foreach (var edge in curNode.Edges) 35 { 36 var nextNode = edge.Next; 37 //1.重新估值 38 if (dist[curNode.Id] + edge.Value < dist[nextNode.Id]) 39 dist[nextNode.Id] = dist[curNode.Id] + edge.Value; 40 } 41 42 //选择dist中最小的值加入到S中 43 curNode = curNode.Edges[0].Next; 44 for (int i = 0; i < dist.Length; i++) 45 { 46 //不在S中且比当前节点的dist值小,则替换 47 if (!S.Contains(Nodes[i]) && 48 dist[i] < dist[curNode.Id]) 49 curNode = Nodes[i]; 50 } 51 S.Add(curNode); 52 //所有元素都加入到S中之后,则结束 53 if (S.Count == Nodes.Count) 54 break; 55 } 56 57 return dist; 58 } 59 60 private static void Main(string[] args) 61 { 62 Graphic graphic = new Graphic() 63 { 64 Nodes = new List<Node>() 65 { 66 new Node(0), 67 new Node(1), 68 new Node(2), 69 new Node(3), 70 new Node(4), 71 } 72 }; 73 74 graphic.Nodes[0].Edges = new List<Edge>() 75 { 76 new Edge() {Value = 10, Next = graphic.Nodes[1]}, 77 new Edge() {Value = 100, Next = graphic.Nodes[4]}, 78 new Edge() {Value = 30, Next = graphic.Nodes[3]}, 79 }; 80 81 graphic.Nodes[1].Edges = new List<Edge>() 82 { 83 new Edge() {Value = 50, Next = graphic.Nodes[2]}, 84 }; 85 86 graphic.Nodes[2].Edges = new List<Edge>() 87 { 88 new Edge() {Value = 10, Next = graphic.Nodes[4]}, 89 }; 90 91 graphic.Nodes[3].Edges = new List<Edge>() 92 { 93 new Edge() {Value = 20, Next = graphic.Nodes[2]}, 94 new Edge() {Value = 60, Next = graphic.Nodes[4]}, 95 }; 96 97 graphic.Nodes[4].Edges = new List<Edge>(); 98 99 var arr = graphic.Dijkstra(); 100 101 for (int i = 0; i < arr.Length; i++) 102 { 103 Console.Write((i + 1) + ":" + arr[i].ToString() + " "); 104 } 105 106 Console.WriteLine(); 107 Console.Read(); 108 } 109 } 110 111 112 internal class Node 113 { 114 public List<Edge> Edges; 115 public int Id; 116 117 public Node(int id) 118 { 119 Id = id; 120 } 121 } 122 123 internal class Edge 124 { 125 public Node Next; 126 public int Value; 127 } 128 }