一,大致的遍歷過程圖解及過程講解
先從開始點尋找與其他邊連接最小的邊
1,如下圖(a)中,找A點與其它五點中C的距離最短弧;
所以連接AC(因爲由圖可知B點無入度,所以可忽略不計);
2,圖(b)將與A點連接的頂點和與C點連接的所有頂點的弧相比較,看誰距離最短,
(因爲此時D點不直接與A相連,而是通過中間點C,所以此時AD的距離可以看作AC+CD)
所以連接AE。
3,圖(c)與A點連接的頂點和與C點連接的頂點和E點連接的所有頂點的弧相比較,看誰距離最短,
此時A點到F點有兩條路:1,AF,2,通過E點再連接A->E->F.
此時A點到D點也有兩條路:1,A->C->D;2,A->E->D;
此時通過比較A->E->D最短。所以連接ED;
4,圖(d)與A點連接的頂點和與C點連接的頂點和E點連接的頂點和D點連接的所有頂點的弧相比較,看誰距離最短,
此時A到F有三條路:1,A->F;
2,A->E->F;
3,A->E->D->F
根據比較長短可知第三種距離最短。所以連接DE。
(因爲B點沒有入度,所以AB之間無連接)
二,實現方法
這種方法除了構造鄰接矩陣所需的結構體和函數之外,加入了三個新數組:
int S[pointMax]; //到所求頂點的最短路徑是否被確定,等於-1代表未被確認
即表示某一點是否被連接(如上圖a中,C點連接,則S[2]賦值爲1,代表該點已確認)
int D[pointMax]; //最短路徑
即表示某點到所求點的距離(如上圖a中,C點確認連接,則D[2]賦值爲10,代表AC距離爲10)
int Path[pointMax]; //連通弧的前驅
爲了防止出現迴路,即某一連通邊都賦值爲一樣,
(如上圖c中,ED連接,此時A->E->D連接,所以A點E點D點的Path[]值一樣
第一步:先構造鄰接矩陣,並賦值,該過程類似於圖的鄰接矩陣儲存法類似。
第二步,先將上面新加入的三個數組進行賦值。
第三步:從所有能連通的弧中,找到一個最小弧,並連通,然後給相對應的三個數組進行賦值改變。
然後第三步繼續循環循環,總共循環(頂點數-1)次。
大致思路都已經在上面的圖中寫出來了,只要將上面的圖理解,大致就會了,三個數組只是輔助遍歷。
實現截圖
這個截圖顯示的信息並不是特別多(如果想知道詳細每一次遍歷後信息,可自行在對應地方添加顯示信息)
四,代碼
#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 S[pointMax]; //到所求頂點的最短路徑是否被確定,等於-1代表未被確認
int D[pointMax]; //最短路徑
int Path[pointMax]; //連通弧的前驅
void SP_DIJ(AMgroup &A, int v0)
{
//初始化過程
int number = A.point; //有向圖中的頂點數
for (int i = 0; i < number; i++)
{
S[i] = -1; //初始爲空-1
D[i] = A.AMchart[v0][i]; //各個頂點到v0的權值
if (D[i] < MaxInt)
{
Path[i] = v0; //如果有邊,則將i的前驅初始化爲v0
}
else
{
Path[i] = -1; //無邊則初始化爲空-1
}
}
S[v0] = 1; //將v0加入S中
D[v0] = 0; //源點到源點的距離爲0
//求最短路徑
int n;
for (int i = 1; i < number; i++)//對其餘number-1個頂點依次進行計算
{
int min = MaxInt;
for (int j = 0; j < number; j++)
{
if (S[j] == -1 && D[j] < min)
{
n = j;
min = D[j];
}
}
cout << n << ":" << min << endl;
S[n] = 1;
for (int j = 0; j < number; j++)
{
if (S[j] == -1 && D[n] + A.AMchart[n][j] < D[j])
{
D[j] = D[n] + A.AMchart[n][j];
Path[j] = n;
}
}
}
cout << endl;
for (int i = 0; i < A.point; i++)
{
if (i != v0)
{
if (D[i] == MaxInt)
{
cout << A.VTchart[v0] << "-->" << A.VTchart[i] << "不連通" << endl;
}
else
{
cout << A.VTchart[v0] << "-->" << A.VTchart[i] << "的最短路徑爲:" << D[i] << endl;
}
}
}
}
int main()
{
AMgroup *A = new AMgroup;
CreatAM(*A);
int m;
cout << "\n從第幾個點開始遍歷:";
cin >> m;
SP_DIJ(*A, m);
system("pause");
}