求最短路径常用算法Dijkstra和Floyd。
1、Dijksta算法
a、首先标记起点。
b、然后循环遍历所有点,如果这个点没被标记,距起点较近,那么用一个变量u记录该点,重复这个过程,保证u点为距离起点最近而且没有被标记的点。
c、标记u点。
d、重新计算u的未标记邻接点v距离起点的最近距离。需要比较该邻接点v距起点的距离与u与起点距离加上边u,v的权重的大小。取较小者。
f、重复b c d过程,直到所有点标记完毕。
#define N 6 // 定义点数
#define M 32767 // 无穷大,两点间没边
int a[N][N]; // 邻接矩阵, a[i][i] = M
int label[N]; // 标记
int dist[N]; // 记录每个点距离起点最近距离
int prev[N]; // 记录最近距离上该点的上一个点
void dijkstra(int start)
{
// 初始化label dist prev
int i;
for(i=0; i<N; i++)
{
label[i] = 0;
dist[i] = a[start][i]; // dist初始为邻接矩阵值
prev[i] = (dist[i] < M) ? start : -1;
}
label[start] = 1; // 标记起点
int j, u, min;
for(i=0; i<N-1; i++) // 循环标记,起点已标,只需循环N-1
{
min = M;
u = -1;
for(j=0; j<N; j++)
{
if(label[j] == 0 && dist[j] < min)
{
min = dist[j];
u = j;
}
}
if(u != -1)
{
label[u] = 1; // 标记u
for(j=0; j<N; j++)
{
// 更新dist prev
if(a[u][j] < M) {
if(label[j] == 0 &&
a[u][j] + dist[u] < dist[j])
{
dist[j] = a[u][j] + dist[u];
prev[j] = u;
}
}
}
}
}
}
2、Floyd算法
可以求解出任意两个顶点间的最短路径长度,求不出路径。
a、构建邻接矩阵a,a[i][i]=0,其它没边的为无穷。
b、三重循环,不断在i, j之间添加经过点,若使距离变短,则保留该经过点。因为i, j, k会出现重复,所以a[i][i] = 0而不是无穷来避免a[i][i]被修改产生环路。
#define N 6 // 定义点数
int a[N][N]; // 邻接矩阵
void floyd()
{
int i, j, k;
for(k=0; k<N; k++)
for(i=0; i<N; i++)
for(j=0; j<N; j++)
if(a[i][j] > a[i][k] + a[k][j])
{
a[i][j] = a[i][k] + a[k][j];
}
}