Floyd
通过Floyd计算图G=(V,E)中各个顶点的最短路径时,需要引入两个矩阵,矩阵S中的元素a[i][j]表示顶点i(第i个顶点)到顶点j(第j个顶点)的距离。矩阵P中的元素b[i][j],表示顶点i到顶点j经过了b[i][j]记录的值所表示的顶点。
假设图G中顶点个数为N,则需要对矩阵D和矩阵P进行N次更新。初始时,矩阵D中顶点a[i][j]的距离为顶点i到顶点j的权值;如果i和j不相邻,则a[i][j]=∞,矩阵P的值为顶点b[i][j]的j的值。 接下来开始,对矩阵D进行N次更新。第1次更新时,如果”a[i][j]的距离” > “a[i][0]+a[0][j]”(a[i][0]+a[0][j]表示”i与j之间经过第1个顶点的距离”),则更新a[i][j]为”a[i][0]+a[0][j]”,更新b[i][j]=b[i][0]。 同理,第k次更新时,如果”a[i][j]的距离” > “a[i][k-1]+a[k-1][j]”,则更新a[i][j]为”a[i][k-1]+a[k-1][j]”,b[i][j]=b[i][k-1]。更新N次之后,完成。
#include <stdio.h>
#define NUMS 12
#define INF 65535
typedef struct
{
char vertex[NUMS];
int edges[NUMS][NUMS];
int n,e;
}Graph;
void Dispath(int A[][NUMS],int path[][NUMS],int n);
void ReadGraph(Graph *G)
{
int i,j;
FILE * fp = fopen("floyd.txt","rw");
G->n = NUMS;
G->e = NUMS * NUMS;
for(i=0; i<NUMS; i++)
{
for(j=0; j<NUMS; j++)
{
fscanf(fp,"%d",&(G->edges[i][j]));
printf("%d \t",G->edges[i][j]);
}
printf("\n");
}
}
void Floyd(Graph G)
{
int A[NUMS][NUMS],path[NUMS][NUMS];
int i,j,k;
for (i=0;i<G.n;i++)
{
for (j=0;j<G.n;j++)
{
A[i][j]=G.edges[i][j];
path[i][j]=-1;
}
}
for (k=0;k<G.n;k++)
{
for (i=0;i<G.n;i++)
{
for (j=0;j<G.n;j++)
{
if (A[i][j]>A[i][k]+A[k][j])
{
A[i][j]=A[i][k]+A[k][j];
path[i][j]=k;
}
}
}
}
Dispath(A,path,G.n);
}
void Ppath(int path[][NUMS],int i,int j)
{
int k;
k=path[i][j];
if (k==-1)
{
return;
}
Ppath(path,i,k);
printf("%d,",k + 1);
Ppath(path,k,j);
}
void Dispath(int A[][NUMS],int path[][NUMS],int n)
{
int i,j;
for (i=0;i<n;i++)
{
for (j=0;j<n;j++)
{
if (A[i][j]==INF)
{
if (i!=j)
{
printf("从%d到%d没有路径\n",i+1,j+1);
}
}
else
{
printf(" 从%d 到 %d => 最短路径长度为 : %d , 路径站点为 :",i+1,j+1,A[i][j]);
printf("%d,",i + 1);
Ppath(path,i,j);
printf("%d\n",j + 1);
}
}
}
}
int main()
{
Graph G;
ReadGraph(&G);
Floyd(G);
return 0;
}
Dijkstra:
1.将图上的初始点看作一个集合S,其它点看作另一个集合
2.根据初始点,求出其它点到初始点的距离d[i] (若相邻,则d[i]为边权值;若不相邻,则d[i]为无限大)
3.选取最小的d[i](记为d[x]),并将此d[i]边对应的点(记为x)加入集合S
4.再根据x,更新跟 x 相邻点 y 的d[y]值:d[y] = min{ d[y], d[x] + 边权值w[x][y] },因为可能把距离调小,所以这个更新操作叫做松弛操作。
5.重复3,4两步,直到目标点也加入了集合,此时目标点所对应的d[i]即为最短路径长度。
void dijkstra(Graph G, int vs, int prev[], int dist[])
{
int i,j,k;
int min;
int tmp;
int flag[MAX]; //
for (i = 0; i < G.vexnum; i++)
{
flag[i] = 0;
prev[i] = 0;
dist[i] = G.matrix[vs][i];
}
flag[vs] = 1;
dist[vs] = 0;
for (i = 1; i < G.vexnum; i++)
{
min = INF;
for (j = 0; j < G.vexnum; j++)
{
if (flag[j]==0 && dist[j]<min)
{
min = dist[j];
k = j;
}
}
flag[k] = 1;
for (j = 0; j < G.vexnum; j++)
{
tmp = (G.matrix[k][j]==INF ? INF : (min + G.matrix[k][j])); // 防止溢出
if (flag[j] == 0 && (tmp < dist[j]) )
{
dist[j] = tmp;
prev[j] = k;
}
}
}
printf("dijkstra(%c): \n", G.vexs[vs]);
for (i = 0; i < G.vexnum; i++)
printf(" shortest(%c, %c)=%d\n", G.vexs[vs], G.vexs[i], dist[i]);
}