131 lines
2.9 KiB
C
131 lines
2.9 KiB
C
/*
|
||
Program: all-pairs-shortest-path-v2.c (Report comments/bugs to chikh@yuntech.edu.tw)
|
||
Function: 修改all-pairs-shortest-path-v1.c使得A與Y矩陣能依圖內的頂點總數作配置,避免
|
||
預先配置過大的100x100陣列空間而形成浪費
|
||
*/
|
||
|
||
#include <stdio.h>
|
||
#include <stdlib.h> /* for exit() */
|
||
|
||
#define Inf 1073741823 /* 此為2^30-1的大數字,為本程式假設的無限大值;可改用limits.h定義的INT_MAX */
|
||
|
||
void init(int ***A, int ***Y) /* 讀取輸入資料檔、設定相鄰矩陣,把相關資料結構作初始化 */
|
||
{
|
||
FILE *fptr;
|
||
int i, j;
|
||
int weight, N;
|
||
|
||
if ((fptr=fopen("shortestPath.dat","r")) == NULL) { /* 開啟資料檔 */
|
||
perror("shortestPath.dat");
|
||
exit(1);
|
||
}
|
||
|
||
fscanf(fptr,"%d",&N); /* 讀取圖形節點數 */
|
||
|
||
*A = (int **)malloc((N+1)*sizeof(int *));
|
||
*Y = (int **)malloc((N+1)*sizeof(int *));
|
||
for (i = 0; i <= N; i++) {
|
||
(*A)[i] = (int *)malloc((N+1)*sizeof(int));
|
||
(*Y)[i] = (int *)malloc((N+1)*sizeof(int));
|
||
}
|
||
|
||
(*A)[0][0] = N;
|
||
for (i = 1; i <= N; i++ )
|
||
for (j = 1; j <= N; j++) {
|
||
(*A)[i][j] = (i==j)? 0: Inf; /* 初始化A[1..N][1..N]相鄰矩陣,所有元素均先預設為∞ */
|
||
(*Y)[i][j] = (i==j)? i: -1;
|
||
}
|
||
|
||
while (fscanf(fptr,"%d %d %d",&i,&j,&weight) != EOF) {
|
||
(*A)[i][j] = weight; /* 讀取連接頂點i與j的邊的權重值 */
|
||
(*Y)[i][j] = i;
|
||
}
|
||
|
||
fclose(fptr);
|
||
}
|
||
|
||
void floydWarshall(int ***A, int ***Y)
|
||
{
|
||
int i, j, k;
|
||
int N = (*A)[0][0]; //無法使用sizeof(A[0])/sizeof(A[0][0])判讀維度,因以malloc()配置所得記憶體空間不具結構
|
||
|
||
for (k = 1; k <= N; k++)
|
||
for (i = 1; i <= N; i++)
|
||
for (j = 1; j <= N; j++)
|
||
if ((*A)[i][k] + (*A)[k][j] < (*A)[i][j]) {
|
||
(*A)[i][j] = (*A)[i][k] + (*A)[k][j];
|
||
(*Y)[i][j] = (*Y)[k][j];
|
||
}
|
||
//上面二層for迴圈用於檢視/修正每二頂點(i,j)之間有否經由k(中繼頂點)能得更小距離值
|
||
}
|
||
|
||
void printMatrix(int **A)
|
||
{
|
||
int i, j;
|
||
int N = A[0][0];
|
||
|
||
for (i = 1; i <= N; i++) {
|
||
for (j = 1; j <= N; j++) {
|
||
if (A[i][j] == Inf)
|
||
printf("%5s","∞");
|
||
else
|
||
printf("%4d",A[i][j]);
|
||
}
|
||
printf("\n");
|
||
}
|
||
}
|
||
|
||
void backtrack(int **Y, int source, int dest)
|
||
{
|
||
int k = Y[source][dest];
|
||
|
||
if (source == dest) {
|
||
printf("頂點%d →",source);
|
||
return;
|
||
}
|
||
if (Y[source][dest] == -1) {
|
||
printf("頂點%d與%d之間沒有路徑存在 ",source,dest);
|
||
return;
|
||
}
|
||
backtrack(Y,source,k);
|
||
printf(" %d →",dest);
|
||
}
|
||
|
||
void traverseMatrix(int **Y)
|
||
{
|
||
int i, j, k, source, sink;
|
||
|
||
printf("\n源點 => ");
|
||
scanf("%d",&source);
|
||
printf("終點 => ");
|
||
scanf("%d",&sink);
|
||
|
||
printf("最短路徑:");
|
||
backtrack(Y,source,sink);
|
||
printf("\b\b ");
|
||
}
|
||
|
||
void freeMemory(int **A, int **Y)
|
||
{
|
||
int i, N = A[0][0];
|
||
|
||
for (i = 0; i <= N; i++) {
|
||
free(A[i]);
|
||
free(Y[i]);
|
||
}
|
||
free(A);
|
||
free(Y);
|
||
}
|
||
|
||
int main() {
|
||
int **A, **Y;
|
||
|
||
init(&A,&Y); /* 讀取輸入資料檔、設定相鄰矩陣,並把相關資料結構作初始化 */
|
||
floydWarshall(&A,&Y);
|
||
printMatrix(A);
|
||
traverseMatrix(Y);
|
||
freeMemory(A,Y);
|
||
|
||
return 0;
|
||
}
|