最小生成樹的構造

最小生成樹

樹也是圖的一個特例

什麼是生成樹?

連通圖的生成樹是包含全部頂點的一個極小連通子圖,即此樹包含圖中所有的頂點,並且只含儘可能少的邊,此樹還是連通
一個圖的生成樹不只一個,權(各邊權值之和)最小的生成樹則爲此圖最小生成樹
最小生成樹具有以下特性:
1、最小生成樹形狀不唯一,但最小生成樹權是唯一的。且爲所有生成樹中最小的
2、最小生成樹邊數爲頂點數減1
3、若無向連通圖邊數比頂點數少1,圖本身就是一棵樹,則最小生成樹是它本身

最小生成樹的構造

構造最小生成樹都利用最小生成樹的同一性質:MST性質
假設N=(V,{E})是一個連通網,U是頂點集V的一個非空子集,如果(u,v)是一條具有最小權值的邊,其中u屬於U,v屬於V-U,則必定存在一顆包含邊(u,v)的最小生成樹
先看下面的兩個算法,結合理解
大體的意思理解爲:首先樹T爲空,在還沒有變成一棵生成樹之前,一直找一條權值最小的邊加入T,並且T不會產生迴路。

普里姆(Prim)算法

首先就是從圖中的一個起點a開始,把a加入U集合,然後,尋找從與a有關聯的邊中,權重最小的那條邊並且該邊的終點b在頂點集合V-U中,我們也把b加入到集合U中,並且輸出邊(a,b)的信息,這樣我們的集合U就有:{a,b},然後,我們尋找與a關聯和b關聯的邊中,權重最小的那條邊並且該邊的終點在集合:(V-U)中,我們把c加入到集合U中,並且輸出對應的那條邊的信息,這樣我們的集合U就有:{a,b,c}這三個元素了,一次類推,直到所有頂點都加入到了集合U。
如下圖例:這樣就找到了圖a的一棵最小生成樹f
在這裏插入圖片描述
簡單僞代碼實現如下:
void Prim(G,T)
{
T=NULL; //初始化空樹
U={w}; // 添加任意頂點
while((V-U)!=NULL) //樹中不含全部頂點即還不是生成樹
{
T=T+(u,v); //將權值最小的邊加入樹中
U=U+{v}; //頂點歸入集合U中
}
}

克魯斯卡爾(Kruskal)算法

Kruskal算法是一種按權值的遞增次序選擇合適的邊來構造最小生成樹的方法
算法思路:
(1)將圖中的所有邊都去掉。
(2)將邊按權值從小到大的順序添加到圖中,保證添加的過程中不會形成環
(3)重複上一步直到連接所有頂點,此時就生成了最小生成樹。這是一種貪心策略。
在這裏插入圖片描述 Kruskal算法僞代碼實現: void Kruskal(V,T) { T=V; //初始化樹T,僅含頂點,也可以說僅含根結點的森林 numS=n; //連通分量數 while(numS>1) { if((u,v)屬於不同的連通分量) { T=T+(u,v); //將權值最小的邊加入生成樹中 numS–; } } }