Dijkstra算法

一 Dijkstra算法

  Dijkstra算法解决了有向图G=(V, E)上带权的单源最短路径问题,但要求所有边的权值非负。Dijkstra算法采用贪心策略。

  最短路径的最优子结构:最短路径的子路径是最短路径。
  从源顶点s出发,可以确认唯一的顶点u1(除非存在顶点v1,其weight(s,v1)=weight(s,u1)),使它的前趋为s,且s->u为最短路径,此时weight(s,u1)在s的各临边中最小。与s相邻的其他顶点,总会通过松弛方法得出最短路径。

  除了邻接表外还有3个数组,当前最短距离distance,前趋顶点pre,是否已访问过顶点(即已确定好最短路径的顶点)visited。

  假设单源顶点为srcIdx,则Dijkstra算法步骤如下:

  ① 初始化:distance设置为INT_MAX,pre设置为-1,visited设为false,distance[srcIdx]=0

  ② 循环VertexNum次:每次从distance中取出visited为false,且distance最短的minIdx,此时将visited[minIdx]变为true,并通过松弛的方法确认minIdx的后续各顶点的最短路径上界。每次循环可以确定源顶点srcIdx到某个顶点的最短路径。

  ③ 递归打印源顶点srcIdx到各顶点的最短路径,及最短长度。

核心代码:

 1 void initializeSingleSource(int srcIdx, int VertexNum, int *distance, int *pre, bool *visited)
 2 {
 3     for (int i=0;i<VertexNum;i++)
 4     {
 5         distance[i] = INT_MAX;
 6         pre[i] = -1;
 7         visited[i] = false;
 8     }
 9     distance[srcIdx] = 0;
10 }
11 
12 int extractMin(bool *visited, int *distance)
13 {// 获取当前距离最短的顶点索引
14     int distanceMax = INT_MAX;
15     int minIdx = -1;
16     for (int j=0;j<VertexNum;j++)
17     {
18         if (visited[j] == false && distance[j] < distanceMax)
19         {
20             distanceMax = distance[j];
21             minIdx = j;
22         }
23     }
24     return minIdx;
25 }
26 
27 void relax(int u, int v, int w, int *d, int *pre)
28 {
29     if (d[v] > d[u] + w)
30     {
31         d[v] = d[u] + w;
32         pre[v] = u;
33     }
34 }
35 
36 void visitPre(int idx, int *pre, int distance)
37 {
38     if (pre[idx] != -1)
39     {
40         visitPre(pre[idx], pre, distance);
41         cout << "-->" << idx;
42     }
43     else
44         cout << idx << "(" << distance << ")";
45 }
46 
47 void printShortestPath(int *pre, int *distance)
48 {
49     cout << "打印最短路径及最短长度:" << endl;
50     for (int i=0;i<VertexNum;i++)
51     {
52         visitPre(i, pre, distance[i]);
53         cout << endl;
54     }
55 }
56 
57 void dijkstra(Vertex *graph, int srcIdx, int VertexNum)
58 {
59     int *distance = new int[VertexNum];
60     int *pre = new int[VertexNum];
61     bool *visited = new bool[VertexNum];
62 
63     initializeSingleSource(srcIdx, VertexNum, distance, pre, visited);
64 
65     for (int i=0;i<VertexNum;i++)
66     {
67         int minIdx = extractMin(visited, distance);
68         visited[minIdx] = true;
69 
70         Vertex *vertex = &graph[minIdx];
71         while (vertex->next)
72         {// 访问该顶点的所有后续顶点,确立当前的最短路径
73             int vIdx = vertex->next->idx;
74             if (visited[vIdx] == false)
75                 relax(minIdx, vIdx, vertex->next->weight, distance, pre);
76             vertex = vertex->next;
77         }
78     }
79 
80     printShortestPath(pre, distance);
81 }

截图:

posted @ 2015-07-19 22:58  yoleimei  阅读(172)  评论(0编辑  收藏  举报