標籤:c語言 資料結構 最小產生樹
我們通過一個例子來看一下最小產生樹的求法。
分別用普裡姆演算法(從A結點開始)和克魯斯卡爾演算法計算的最小產生樹。
ok,首先運用Prim演算法進行計算:
| U |
V-U |
B |
C |
D |
E |
F |
TE |
| {A} |
{B,C,D,E,F} |
AB 11 |
AC 13 |
~ ∞ |
AE 16 |
~ ∞ |
AB 11 |
| {A,B} |
{C,D,E,F} |
|
BC 7 |
BD 3 |
AE 16 |
BF 5 |
BD 3 |
| {A,B,D} |
{C,E,F} |
|
BC 7 |
|
AE 16 |
BF 5 |
BF 5 |
| {A,B,D,F} |
{C,E} |
|
BC 7 |
|
FE 12 |
|
BC 7 |
| {A,B,D,F,C} |
{E} |
|
|
|
FE 12 |
|
FE 12 |
| {A,B,D,F,C,E} |
{} |
|
|
|
|
|
|
圖表可能看著有點亂,沒關係,我們先來看一下Prim演算法的基本思想:假設N=(V,{E})是連通圖,TE是N上最小產生樹中邊的集合。演算法從U={u0}(u0∈V),TE={}開始,重複執行下述操作:在所有u∈U, v∈V-U的邊(u,v)∈E中找一條代價最小的邊(u0,v0)併入集合TE,同時v0併入U,直至U=V為止。此時TE中必有n-1條邊,則T=(V,{TE})為N的最小產生樹。
那麼對照例圖和表格我們就很容易地可以看出該演算法的計算流程,首先從結點A開始,分別寫出與其他結點的路徑和權值,如果不連通則取權值為無窮,於是就有了表格的第二行,TE取代價最小的AB;然後將B添加到U,寫出結點B與其他結點的路徑和相應的權值,當然A就不用再寫了,大家可以看到,凡是添加到最小產生樹中的路徑,之後該列則為空白,因為它已經是代價最小的邊,不可能再有其他邊比它更小了;還有一個問題。為了方便起見,在同一列中,如果對應邊的權值不小於其前一個,則將其直接落下來,這樣就可以只比較那個“更小的”,這樣就不用每一行都去比較了;按照這個思路,表格的第三行,BD的權值為3,小於其前一個的權值無窮,則寫入3;第五行,FE的權值為12,小於其前一個AE的權值16,所以寫入12;其實每一行和每一列都是在找那個代價最小的路徑,這樣求得的集合就是最小產生樹,當然還得加入結點的集合,這樣所示表格也就不難理解了,每一行找到一條代價最小的路徑,加入TE,然後將結點加入U,再去比較其他的路徑,就這樣一直走下去,最後得到最小產生樹集合。
接下來進入克魯斯卡爾演算法:
首先看一下它的基本思想:先構造一個只含 n 個頂點的子圖 SG,然後從權值最小的邊開始,若它的添加不使SG 中產生迴路,則在 SG 上加上這條邊,如此重複,直至加上 n-1 條邊為止。一句話,“不構成環的情況下,每次選取最小邊” 。它的出發點就是為使產生樹上邊的權值之和達到最小,則應使產生樹中每一條邊的權值儘可能地小。因此我們就從權值最小的邊開始構造,前提是不構成環。
那麼我們直接找權值最小的邊進行組合,首先是BD,然後是BF,BC,CF不行,因為其構成了環,AB可以,EF也可以,ok,這樣就得到了最小產生樹邊的集合TE={BD,BF,BC,AB,EF},是不是比Prim演算法簡單的多?!
所以該圖的最小產生樹可以表示為T=({A,B,D,F,C,E},{BD,BF,BC,AB,EF}),當然最好還是可以畫出圖來,這樣會更加直接明了。