佛洛依德算法的學習與實現


1、問題引入

  帶權有向圖中單源點的最短路徑問題可以用地傑斯特拉算法求解,如果要求解圖中每一對頂點之間的最短路徑,類似可以想到的方法為:每次以一個頂點為源點,重復執行地傑斯特拉算法算法n次,這樣,便可以求得每一對頂點之間的最短路徑,總的執行時間為O(n3)。

  這里可以采用另外一種求解算法:Floyd算法。

2、Floyd的基本思想為:

  從鄰接矩陣a開始進行n次迭代,第一次迭代后a[i,j]的值是從vi到vj且中間不經過變化大於1的頂點的最短路徑長度;第k次迭代后a[i,j]的值是從vi到vj且中間不經過變化大於k的頂點的最短路徑長度 第n次迭代后a[i,j]的值就是從vi到vj的最短路徑長度。

3、算法描述:

  (1) 用數組d[i][j]來記錄i,j之間的最短距離。初始化d[i][j],若i=j則d[i][j]=0,
    若i,j之間有邊連接則d[i][j]的值為該邊的權值,否則d[i][j]的值為max 。
  (2) 對所有的k值從1到n,修正任意兩點之間的最短距離,計算d[i][k]+d[k][j]的值,
    若小於d[i][j],則d[i][j]= d[i][k]+d[k][j],否則d[i][j]的值不變。

4、具體實現:

  帶權有向圖如下:

在2.txt文件中保存的帶權有向圖的數據為:

其中第一個數據4表述圖中有4個節點,其他的四行四列數據表示各個節點之間的路徑長度,9999表示兩個節點之間不可達。

具體代碼為:

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 #define max 9999
 4 void Floyd(int,int **,int**,int**);
 5 void Searchpath(int,int,int**,int**);
 6 void main()
 7 {
 8     int i,j,num,first,last;
 9     FILE *p;
10     p=fopen("2.txt","r");
11     if(p==NULL)
12     {
13         printf("無法打開2.txt");
14         exit(-1);
15     }
16     fscanf(p,"%d",&num);//獲取點的個數;
17     int **a=(int**)malloc(sizeof(int*)*num);
18     for(i=0;i<num;i++)
19         a[i]=(int*)malloc(sizeof(int)*num);
20     for(i=0;i<num;i++)//獲取圖中各個點之間的路徑長度;
21         for(j=0;j<num;j++)
22             fscanf(p,"%d",&a[i][j]);
23     //path[i][j]用於記錄從i到j的最短路徑上j點的前一個節點
24     int **path=(int**)malloc(sizeof(int*)*num);
25     for(i=0;i<num;i++)
26         path[i]=(int*)malloc(sizeof(int)*num);
27     //d[i][j]用於記錄從i到j的最短路徑的長度
28     int **d=(int**)malloc(sizeof(int*)*num);
29     for(i=0;i<num;i++)
30         d[i]=(int*)malloc(sizeof(int)*num);
31     //佛洛依德算法程序調用
32     Floyd(num,path,d,a);
33     printf("最終得到的距離矩陣為:\n");
34     for(i=0;i<num;i++)
35     {
36         for(j=0;j<num;j++)
37             printf("%d  ",d[i][j]);
38         printf("\n");
39     }
40     printf("請輸入起始點(小於%d):",num);
41     scanf("%d",&first);
42     printf("\n請輸入終止點(小於%d):",num);
43     scanf("%d",&last);
44     printf("起始點%d到終止點%d的最短路徑長度為:%d\n",first,last,d[first][last]);
45     Searchpath(first,last,path,d);//利用path[i][j]得出從i到j的最短路徑
46 }
47 void Floyd(int num,int **path,int**d,int **a)
48 {
49     int i,j,k;
50     for(i=0;i<num;i++)
51     {
52         for(j=0;j<num;j++)//初始化
53         {
54             if(a[i][j]<max) path[i][j]=j;//從i到j有路徑
55             else path[i][j]=-1;
56             d[i][j]=a[i][j];
57         }
58     }
59     for(k=0;k<num;k++)
60         for(i=0;i<num;i++)
61             for(j=0;j<num;j++)
62                 if(d[i][j]>d[i][k]+d[k][j])//從i到j的一條更短的路徑
63                 {
64                     d[i][j]=d[i][k]+d[k][j];
65                     path[i][j]=path[i][k];
66                 }
67 }
68 void Searchpath(int first,int last,int **path,int**d)
69 {
70     int k;
71     if(d[first][last]==max)
72         printf("起始點%d到終止點%d不可達",first,last);
73     else
74     {
75         printf("起始點到終點的路徑為:");
76         k=last;
77         printf("%d <-- ",k);
78         while((k!=first)&&(k!=path[first][k]))
79         {
80             k=path[first][k];
81             printf("%d <-- ",k);
82             if(k==path[first][k])
83                 k=first;
84         }
85         printf("%d\n",first);
86     }
87 }

5、參考資料:

  (1)嚴蔚敏,數據結構。

  (2)http://blog.sina.com.cn/s/blog_3fe961ae0100nl6g.html

  (3)http://zhidao.baidu.com/question/349458736.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM