Prim演算法 最小生成樹
阿新 • • 發佈:2018-11-22
最小生成樹概念;
最小生成樹是從圖中生成的,圖要連通才會有最小生成樹,反之,有最小生成樹的圖一定連通;
最小生成樹要包含圖中的所有頂點,最小生成樹的所有邊也必須包含在圖中;
最小生成樹無迴路,有V個頂點,有V-1條邊;
Prim演算法求最小生成樹:
貪心思想: 每一步都求出最優的解,經過N步,就會得到最優解,也就是最小生成樹;
// 當前圖G為鄰接表儲存
int Prim(Graph G,Graph MST) // 最小生成樹用鄰接表表示
{
int dist[Maxnum] // 儲存各個節點和最小生成樹距離
int parent[Maxnum] // 儲存各個節點的父節點
int Vcount; // 儲存樹節點的個數
int totalWeight; // 儲存最小生成樹的權重;
int V;
Adj W; // 鄰接表的節點
Edge E; // 邊
for(V = 0;V < G->Nv ;V++) //初始化
{
dist[V] = INFINITY;
parent[V] = 0; // 從0節點開始生成最小生成樹;
}
for(W=G->G[0].FirstEdge;W;W=W->nxet)
{
dist[W->AdjV] = W->Weight; // 更新距離
}
// 初始化
Vcount = 0;
totalWeight = 0;
E = (Edge)malloc(sizeof(struct ENode));
// 收錄0節點
dist[0] = 0; //為0值代表已收錄進最小生成樹
parent[0] = -1; //0是最小生成樹的根節點,父節點不存在,為-1;
Vcount++; // 更新樹頂點的個數
while(1)
{
V = Findmin(G,dist); // 找出最小值
if(V==-1) // 判斷最小值是否有意義
break;
// 構造邊 V1到V2的有向邊
E->V1 = parent[V];
E->V2 = V;
E->Weight = dist[V];
// 更新樹
InsertEdge(MST, E); //插入邊
dist[V] = 0;
Vcount++;
totalWeight += dist[V];
// 每收錄一個節點, 都要更新最小樹的距離,最後得到最優解
for(W = G->G[V].FirstEdge;W;W=w->nxet) //更新各點距離最小樹的距離
{
if(dist[W->AdjV]!= 0 && W->Weight < dist[W->AdjV])
{
dist[W->AdjV] = W->Weight; // 更新距離
parent[W->AdjV] = V; // 更新父節點
}
}
}
if(Vcount<G->Nv) //判斷是否生成了最小生成樹
{
totalWeight = -1;
}
return totalWeight; // 返回最小生成樹的權重
}
int Findmin(Graph G , int dist[]) // 找出距離最小生成樹最近的節點
{
int Mindist = INFINITY; // 儲存最小值
int Mv; // 儲存值的下標
for(int V = 0; V<G->Nv;V++)
{
if(dist[V]!=0 && dist[V]<Mindist) //未被收錄且小於最小值
{
Mindist = dist[V];
Mv = V;
}
}
if(Mindist < INFINITY)
{
return Mv;
}
return -1;
}