/* 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 #include /* 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; }