1. 程式人生 > >Prim演算法 最小生成樹

Prim演算法 最小生成樹

最小生成樹概念;
最小生成樹是從圖中生成的,圖要連通才會有最小生成樹,反之,有最小生成樹的圖一定連通;
最小生成樹要包含圖中的所有頂點,最小生成樹的所有邊也必須包含在圖中;
最小生成樹無迴路,有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;
}