概述
Prim算法是應用貪心算法設計策略實現的生成最小支撐樹的算法,又稱為加點法。與其類似的是Kruskal算法,又稱為加邊法。
什么是最小支撐樹
MST性質及其證明
Prim和kruskal都是貪心策略。
都是利用了MST性質。
Prim算法基本思想
設G=(V,E) 是一個連通賦權圖,V={1,2,...,n}。
1. 設置一個空集S。
2. 隨機選擇一個頂點作為起始加入S,例如加入1,S={1}.
3. 作貪心選擇:從V-S中選取 j 加入S,j 要滿足<i,j>為最小,i∈S。
4. 重復3直至S中包含所有頂點。
Prim算法C實現
1.算法描述
關鍵之處在于如何選擇最小的<i,j>,因此設置兩個數組lowcost,closest。
lowcost[i] = Min(lowcost[i],<i,j>) ,j∈S。
lowcost[i]存儲V-S中 i 頂點到S各頂點的邊中的最小邊權值,例如,S中有頂點1,2,則lowcost[i] = MIn{ <i,1>,<i,2>}。
closest[i] 存儲lowcost[i]最小邊的另一頂點。
S中有頂點1,2,則lowcost[i] = MIn{ <i,1>,<i,2>},假設<i,2>最小則closest[i]=2。
故prim算法可分為如下3部分
1. 初始化lowcost和closest數組,和S數組(S[i]=1,表示i頂點已經進入S集和)
選擇一個初始頂點start,lowcost初始化,lowcost[i]=<i,start>,closest[i]=start。
2. 找到遍歷 lowcost 找最小,如lowcost[k]最小且k不在S中,k加入S,k∈V-S。
3. k加入S后 要更新lowcost和closest。
此時遍歷lowcost,locost[i] = Min{Min(lowcost[i],<i,k>) },k為剛加入S中的頂點,i∈V-S。
若lowcost[i] > <i,k> ,則lowcost[i] = <i,k>,closest[i] = k.
4.重復2,3直至S中包含所有頂點。
2.代碼
void Prim(int *lowcost,int *closest,Graph G)
{
int count=1,min,*s,start,k,*lowcost,*closest;
s = malloc((G->n+1)*sizeof(int));
start =1;
lowcost = malloc((G->n+1)*sizeof(WItem));
closest = malloc((G->n+1)*sizeof(int));
// 初始化數組
for(int i=1;i<=G->n;i++){
lowcost[i] = G->a[i][start];
closest[i]=start;
s[i]=0;
}
s[start]=1;printf(" %d ",start);
while(count<G->n){
// 找最小邊
min = G->NoEdge;
for(int i=1;i<=G->n;i++ )
if(lowcost[i]<min && (!s[i]))
{
min = lowcost[i];
k=i;
}
// k加入S
s[k]=1;
count++;
printf(" %d ",k);
// 更新數組
for(int i=1;i<=G->n;i++)
if(G->a[i][k] < lowcost[i] && (!s[i]))
{ lowcost[i] = G->a[i][k];
closest[i] = k;
}
}// while
}