7.4.1 prim算法
用prim算法求圖的最小生成樹:
1) 由兩個數組記錄prim求最小生成樹的過程中所需的信息
a) Lowcost[Max],記錄最小生成樹中每個【葉子結點】和【其他頂點】組成的所有邊的權重,沒有邊的,權重就是
i. 長度就是頂點的個數
b) Adjvex[Max],記錄Lowcost[Max]數組中,每條邊所對應的一個頂點,也就是說,這個邊是屬於這個頂點的,Adjvex[Max]記錄的就是這個頂點在圖中的下標(可以比喻成是一個線性函數,Adjvex[Max]就是自變量的集合,Lowcost[Max]就是函數值的集合)
c) Adjvex[Max] 的 元素 與 元素對應的下標構成的邊,是在最小生成書中的,對應下標的Adjvex[Max]的元素,就是這條邊的權重
d) 有這麼幾個要解決的問題:
i. 選出Lowcost[Max]數組中的元素
1. Lowcost[0] = 0 ,Adjvex[0] = 0 -> 將V0添加到最小生成樹中,也就是最小生成樹的根
2. Lowcost數組的初始值就是【V0參與生成所有邊的權重】的集合
ii. 根據Lowcost[Max]數組數據與 鄰接矩陣中,第【最小生成樹新添加頂點的下標】行的數據比較,確定Adjvex[Max]數組的元素,並且將較小的邊,替換Lowcost[Max]中對應下標的邊(相當於是設置自變量,和函數值)
iii. 選出Lowcost[Max]數組後,找出最小的權重的邊,並添加到最小生成樹,權重爲0,就算是添加到最小生成樹中,所以每次選出之後,都要將Lowcost[i] = 0,k =i (記錄最小權重邊的下標)(一旦成爲最小生成樹的一部分,權重(函數值)=0)
(Adjvex[k],k)就是當前的最小權重邊
iv. 將鄰接矩陣中的第k行的數據與 Lowcost數組中的比較
滿足(lowcost[j] !=0 && arc[k][j] < lowcost[j])
è lowcost[j] = arc[k][j] Adjvex[j] = k
這其實就是將【新添加到最小生成樹中的邊】的【另一個頂點(比如V1)所參加生成的邊中(權重信息存儲在鄰接矩陣的第1行),權重小於lowcost對應的值的邊】添加到lowcost數組中
lowcost[j]!=0 表示已經在最小生成樹中的邊不參與比較
2) 代碼解析:
void MiniSpanTree_Prim(MGraph G)
{
int min,i,j,k;
int adjvex[Max]; //存儲lowcost[]存儲的邊的一個頂點,元素與對應下標組成邊
int lowcost[Max]; //存儲最小生成樹所有葉子結點的所有邊的權重
lowcost[0] = 0; //將V0放到最小生成樹中,V0到V0是沒有權值的
adjvex[0] = 0; // V0到V0是沒有邊的
//初始化兩個數組
for(i = 1;i < G.numVertex; i++)
{
lowcost[i] = G.arc[0][i];
adjvex[i]= 0;
}
//循環圖中的每一個頂點
for(i = 1; i < G.numVertex;i++)
{
min = 65535;
j = 1; //因爲V0已經在最小生成樹中,所以從下標爲1的頂點開始
k = 0;
while(j < G.numVertex)
{
// lowcost[i] != 0 表示頂點沒有在最小生成樹中
// lowcost[i] <min 找出當前lowcost數組中最小的元素
if(lowcost[i] != 0&& lowcost[i] < min)
{
min =lowcost[i];
k = j;
}
j++;
}
cout << adjvex[k]<< k; //可以是其他的操作
lowcost[k] = 0; //將lowcost數組中最小元素置0(也就是附在頂點k上的某條邊的權重置0,表示k頂點加入最小生成樹中)
//更新lowcost數組元素,將現有的lowcost數組中的元素,依次與鄰接矩陣第k行元素比較,較小的就替換lowcost數組中對應的元素
// lowcost[j] != 0表示已經在最小生成樹中的頂點不用遍歷
for(j = 1; j <G.numVertex; j++)
{
if(lowcost[j] != 0&& G.arc[k][j] < lowcost[j])
{
//依次與鄰接矩陣第k行元素比較,較小的就替換lowcost數組中對應的元素
lowcost[j] =G.arc[k][j];
adjvex[j] =k; //將下標爲k的頂點存入adjvex數組,k,j 組成一條邊
}
}
}
}