弗洛伊德算法求的是每一對頂點之間(n->n)的最短路徑,而迪傑斯特拉算法求得是某一點到其它頂點(1->n)的最短路徑
所以第一種方法就是將迪傑斯特拉算法循環n次。
第二種就是直接運用弗洛伊德算法:
原圖:
一,大致過程演示解釋
這裏只說所有頂點經過A點得到的最短路徑(可以先看後面關於方法的解釋,再來理解這段話)
- 首先A點經過A得到最短路徑,顯然可知都不變。
- 然後B點經過A點得到最短路徑,即將B點與其它點的連線與BA和A到其他點連線相比較(eg:求AC之間最短路徑,將AC與AB+BC相比較。)因爲是有向圖,所以由圖可知B到A無連接,所以仍無變化。
- 再看C點經過A點得到的最短路徑:因爲CA+AB<CB;CA+AD<CD。所以此時CB的距離變爲CA+AB=4,CD=CA+AD=7
- 最後D點經過A點得到的最短路徑,因爲D點與A點無有向線段連接,所以無變化。
二,實現方法
這一種求最短路徑的方法除了需要構造鄰接矩陣所需的結構體和函數之外,又入了兩個新數組:
int Path[i][j]; //最短路徑上頂點j的前一頂點(我感覺這個數組沒什麼用,加不加都可以)
int Len[i][j]; //i點與j點的最短路徑
即表示某點到所求點的距離(如上圖中C點經過A到B,因爲CA+AB<CB,所以原Len[C][B]等於5變成現在的4)。
- 先構造鄰接矩陣,並賦值,該過程類似於圖的鄰接矩陣儲存法類似。
- 先將上面新加入的數組進行賦值。
- 進行弗洛伊德算法:感覺這算法也有點像暴力算法。
就是通過三個遍歷進行。先確定一箇中間值,然後比較兩個頂點是直接連接小還是通過中間值連接小
(eg:比如中間值是B,兩個頂點是A和C,則比較AC與AB+BC的值)。
- 然後第三步繼續循環循環,直到程序結束。
三,運行截圖
循環遍歷過程中以四個點爲中間點依次遍歷的過程
四,代碼
#include<iostream>
#include<stdlib.h>
using namespace std;
#define pointMax 100
#define MaxInt 32767
struct AMgroup
{
char VTchart[pointMax]; //頂點表
int AMchart[pointMax][pointMax]; //鄰接矩陣
int point, vert; //點,邊
};
int AMlocate(AMgroup A, char x)
{
for (int i = 0; i < A.point; i++) //依次輸入點的信息
{
if (A.VTchart[i] == x)
{
return i;
break;
}
}
}
void CreatAM(AMgroup &A)
{
cout << "輸入鄰接矩陣頂點數:"; //第一步
cin >> A.point;
cout << "輸入鄰接矩陣邊數:";
cin >> A.vert;
getchar();
char a[100];
cout << "輸入點的信息:"; //第二步
gets_s(a);
for (int i = 0; i < A.point; i++) //依次輸入點的信息
{
A.VTchart[i] = a[i];
}
for (int i = 0; i < A.point; i++) //初始換鄰接矩陣,邊的權值均設爲最大
{
for (int j = 0; j < A.point; j++)
{
A.AMchart[i][j] = MaxInt;
}
}
cout << endl;
char v1, v2; int len;
for (int i = 1; i <= A.vert; i++) //構造鄰接矩陣
{
cout << "輸入第" << i << "條邊的兩個頂點以及權值:";
cin >> v1 >> v2 >> len;
int m, n;
m = AMlocate(A, v1);
n = AMlocate(A, v2);
A.AMchart[m][n] = len;
}
}
int Path[pointMax][pointMax]; //最短路徑上頂點v的前一頂點的序號
int D[pointMax][pointMax]; //記錄兩點間的最短路徑
void Show(AMgroup &A)
{
cout << endl << endl;
for (int i = 0; i < A.point; i++)
{
for (int j = 0; j < A.point; j++)
{
if (A.AMchart[i][j] == MaxInt)
{
cout << "0" << " ";
}
else
{
cout << A.AMchart[i][j] << " ";
}
}
cout << endl;
}
}
void SP_Floy(AMgroup &A)
{
for (int i = 0; i < A.point; i++)
{
for (int j = 0; j < A.point; j++)
{
if (A.AMchart[i][j] < MaxInt && i != j) //如果i和j之間有弧
{
Path[i][j] = i;
}
else
{
Path[i][j] = -1;
}
}
}
for (int i = 0; i < A.point; i++)
{
for (int j = 0; j < A.point; j++)
{
cout << endl;
cout << A.VTchart[j] << "經過" << A.VTchart[i] << "點到其他點" << endl;
for (int k = 0; k < A.point; k++)
{
if (A.AMchart[j][i] + A.AMchart[i][k] < A.AMchart[j][k] && j != k)
{
A.AMchart[j][k] = A.AMchart[j][i] + A.AMchart[i][k];
Path[j][k] = Path[i][k];
}
}
Show(A);
}
}
}
int main()
{
AMgroup *A = new AMgroup;
CreatAM(*A);
SP_Floy(*A);
system("pause");
}