dijkstra算法
简介:
dijkstra算法是由荷兰计算机科学家dijkstra于1959 年提出的。是从一个顶点到其余各顶点的最短路径算法,解决的是有向图中最短路径问题。dijkstra算法主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。
缺点:
1. 该算法要求图中不存在负权边。
2. 由于dijkstra算法主要计算从源点到其他所有点的最短路径,所以算法的效率较低。
3. 一次算法不能得到任意两点的最短距离,得到的仅是任意一点到其它任意点的最短距离。
算法流程图:
算法示例图:
伪代码:
1 function Dijkstra(G, w, s)
2 for each vertex v in V[G] // 初始化
3 d[v] := infinity
4 previous[v] := undefined
5 d[s] := 0
6 S := empty set
7 Q := set of all vertices
8 while Q is not an empty set // Dijstra算法主体
9 u := Extract_Min(Q)
10 S := S union {u}
11 for each edge (u,v) outgoing from u
12 if d[v] > d[u] + w(u,v) // 拓展边(u,v)
13 d[v] := d[u] + w(u,v)
14 previous[v] := u
计算复杂度:
行2--4的初始化对n个顶点进行,显然是O(n)
5--6行O(1)
7行n个顶点入队列O(n)
8行--14行,从8行可以看出进行了n遍循环,每遍在第九行调用一次ExtractMin过程,ExtractMin过程需要搜寻邻接表,每一次需要搜寻整个数组,所以一次操作时间是O(n);11行到14行对节点u的邻接表中的边进行检查,总共有|E|次(总共.每条边最多检查一次),因此是O(E);合起来就是O(E+n*n) = O(n^2);
以上合起来就是O(n)+O(1)+O(n)+O(n^2) == O(n^2).
编程实现:
#include<stdio.h>
#define POINT_CNT 9
int d[POINT_CNT] = {0};
int p[POINT_CNT] = {0};
int visited[POINT_CNT] = {0};
int w[POINT_CNT][POINT_CNT] = {{0, 2, -1, 9, 6, -1, -1, -1, -1},
{-1, 0, 1, -1, 3, -1, -1, -1, -1},
{-1, -1, 0, -1, 1, -1, 6, -1, -1},
{-1, -1, -1, 0, -1, -1, -1, 4, -1},
{-1, -1, -1, 2, 0, 9, -1, 7, -1},
{-1, -1, -1, -1, -1, 0, 5, -1, 1},
{-1, -1, -1, -1, -1, -1, 0, -1, 5},
{-1, -1, -1, -1, -1, 1, -1, 0, 5},
{-1, -1, -1, -1, -1, -1, -1, -1, 0}};
//update the d and p, the distance of point who is near the the_one
void update_d_p(unsigned int the_one)
{
for (unsigned int i = 0; i < POINT_CNT; i++)
{
if (visited[i] == 0 && w[the_one][i] != -1)//i near the_one
{
if (d[i] = -1 || d[i] > d[the_one] + w[the_one][i])
{
d[i] = d[the_one] + w[the_one][i];
p[i] = the_one;
}
}
}
}
int get_min_point()
{
int min = -1;
int min_point = -1;
for (unsigned int i = 0; i < POINT_CNT; i++)
{
if (visited[i] == 0)
{
if (d[i] != -1)
{
if (min == -1 || min > d[i])
{
min = d[i];
min_point = i;
}
}
}
}
return min_point;
}
int main()
{
for (unsigned int i = 0; i < POINT_CNT; i++)
{
d[i] = -1;
p[i] = -1;
}
d[0] = 0;
p[0] = -1;
visited[0] = 1;
update_d_p(0);
int min_point = -1;
while ((min_point = get_min_point()) != -1)
{
visited[min_point] = 1;
update_d_p(min_point);
}
for (unsigned int i = 0; i < POINT_CNT; i++)
{
printf("d[%d] = %d; ", i, d[i]);
printf("p[%d] = %d\n", i, p[i]);
}
return 0;
}