1. 程式人生 > >無向帶權圖的最小生成樹演算法——Prim及Kruskal演算法思路

無向帶權圖的最小生成樹演算法——Prim及Kruskal演算法思路

邊賦以權值的圖稱為網或帶權圖,帶權圖的生成樹也是帶權的,生成樹T各邊的權值總和稱為該樹的權。

   最小生成樹(MST):權值最小的生成樹。

   生成樹和最小生成樹的應用:要連通n個城市需要n-1條邊線路。可以把邊上的權值解釋為線路的造價。則最小生成樹表示使其造價最小的生成樹。

   構造網的最小生成樹必須解決下面兩個問題:

    1、儘可能選取權值小的邊,但不能構成迴路

    2、選取n-1條恰當的邊以連通n個頂點;

    MST性質:假設G=(V,E)是一個連通網,U是頂點V的一個非空子集。若(u,v)是一條具有最小權值的邊,其中u∈U,v∈V-U,則必存在一棵包含邊(u,v)的最小生成樹。 

1.prim演算法

  基本思想:假設G=(V,E)是連通的,TE是G上最小生成樹中邊的集合。演算法從U={u0}(u0∈V)、TE={}開始。重複執行下列操作:

   在所有u∈U,v∈V-U的邊(u,v)∈E中找一條權值最小的邊(u0,v0)併入集合TE中,同時v0併入U,直到V=U為止。

   此時,TE中必有n-1條邊,T=(V,TE)為G的最小生成樹。

   Prim演算法的核心:始終保持TE中的邊集構成一棵生成樹。

注意:prim演算法適合稠密圖,其時間複雜度為O(n^2),其時間複雜度與邊得數目無關

看了上面一大段文字是不是感覺有點暈啊,為了更好理解我在這裡舉一個例子,示例如下:

(1)圖中有6個頂點v1-v6,每條邊的邊權值都在圖上;在進行prim演算法時,我先隨意選擇一個頂點作為起始點,當然我們一般選擇v1作為起始點,好,現在我們設U集合為當前所找到最小生成樹裡面的頂點,TE集合為所找到的邊,現在狀態如下:

U={v1}; TE={};

(2)現在查詢一個頂點在U集合中,另一個頂點在V-U集合中的最小權值,如下圖,在紅線相交的線上找最小值。

通過圖中我們可以看到邊v1-v3的權值最小為1,那麼將v3加入到U集合,(v1,v3)加入到TE,狀態如下:

U={v1,v3}; TE={(v1,v3)};

(3)繼續尋找,現在狀態為U={v1,v3}; TE={(v1,v3)};在與紅線相交的邊上查詢最小值

我們可以找到最小的權值為(v3,v6)=4,那麼我們將v6加入到U集合,並將最小邊加入到TE集合,那麼加入後狀態如下:

U={v1,v3,v6}; TE={(v1,v3),(v3,v6)}; 如此迴圈一下直到找到所有頂點為止。

(4)下影象我們展示了全部的查詢過程:

克魯斯卡爾(Kruskal)演算法(只與邊相關)

演算法描述:克魯斯卡爾演算法需要對圖的邊進行訪問,所以克魯斯卡爾演算法的時間複雜度只和邊又關係,可以證明其時間複雜度為O(eloge)。

演算法過程:

1.將圖各邊按照權值進行排序

2.將圖遍歷一次,找出權值最小的邊,(條件:此次找出的邊不能和已加入最小生成樹集合的邊構成環),若符合條件,則加入最小生成樹的集合中。不符合條件則繼續遍歷圖,尋找下一個最小權值的邊。

3.遞迴重複步驟1,直到找出n-1條邊為止(設圖有n個結點,則最小生成樹的邊數應為n-1條),演算法結束。得到的就是此圖的最小生成樹。

克魯斯卡爾(Kruskal)演算法因為只與邊相關,則適合求稀疏圖的最小生成樹。而prime演算法因為只與頂點有關,所以適合求稠密圖的最小生成樹。

kruskal演算法的時間複雜度為O(eloge)跟邊的數目有關,適合稀疏圖


演算法描述:克魯斯卡爾演算法需要對圖的邊進行訪問,所以克魯斯卡爾演算法的時間複雜度只和邊又關係,可以證明其時間複雜度為O(ElogE)。

演算法過程:

1.將圖各邊按照權值進行排序

2.將圖遍歷一次,找出權值最小的邊,(條件:此次找出的邊不能和已加入最小生成樹集合的邊構成環),若符合條件,則加入最小生成樹的集合中。不符合條件則繼續遍歷圖,尋找下一個最小權值的邊。

3.遞迴重複步驟1,直到找出n-1條邊為止(設圖有n個結點,則最小生成樹的邊數應為n-1條),演算法結束。得到的就是此圖的最小生成樹。判斷是否構成環:《演算法導論》提供的一種方法是採用一種"不相交集合資料結構",也就是並查集了。核心內容就是如果某兩個節點屬於同一棵樹,那麼將它們合併後一定會形成迴路

克魯斯卡爾(Kruskal)演算法因為只與邊相關,則適合求稀疏圖的最小生成樹。而prime演算法因為只與頂點有關,所以適合求稠密圖的最小生成樹。