1. 程式人生 > >最小生成樹演算法(python實現)

最小生成樹演算法(python實現)

Kruskal演算法

Kruskal演算法是一種構造最小生成樹的簡單演算法,其中的思想比較簡單。
基本思想
設G=(V,E)是一個網路,其中|V|=n。Kruskal演算法構造最小生成樹的過程是:

  • 初始時取包含G中所有n個頂點但沒有任何邊的孤立點子圖T=(V,{}),T裡的每個頂點自成一個連通分量。下面將通過不斷擴充T的方式構造G的最小生成樹。
  • 將邊集E中的邊按權值遞增的順序排序,在構造中的每一步順序地檢查這個邊序列,找到下一條(最短的)兩端點位於T的兩個不同連通分量的邊e,把e加人T。這導致兩個連通分量由於邊e的連線而變成了一個連通分量。
  • 每次操作使T減少一個連通分量。不斷重複這個動作加人新邊,直到T中所有頂點都包含在一個連通分量裡為止,這個連通分量就是G的一棵最小生成樹。

 可以先用一個優先佇列儲存所有的邊,這樣可保證每次取到的都是最短邊。為每個連通分量確定一個代表元,如果兩個頂點的代表元相同,它們就互相連通,屬於同一連通分量。。加人一條邊減少了連通分量,這時需要選一個頂點,讓被合併的兩個連通分量裡的頂點都以它為代表元。完成這件事的簡單方法是從原來的兩個代表元中任選一個,而後更新另一連通分量中頂點的代表元。

演算法的python實現

下面給出Kruskal演算法的一個實現。除表reps和mgt外,這個演算法還使用了另一個表edges,在其中儲存圖graph所有的邊,並呼叫Python表的sort操作將這些邊按權值從小到大排好序。隨後的操作就是逐個選擇最短的有效邊。
邊表的形式是(w,vi,vj),其中w是這條邊的權值,vi和vj是其兩個端點。在主迴圈裡順序檢查edges裡的邊(按權值從小到大),如果一條邊的兩端點代表元不同,就將其加人mst,並更新一個連通分量的代表元。這樣反覆做到mst裡積累了n-1條邊(成功得到最小生成樹),或者所有邊都已檢查完畢(沒有最小生成樹),迴圈結束。這時在mst裡儲存的是graph的最小生成樹,或最小生成樹林。

#Kruskal演算法
def Kruskal(graph):
    vnum=graph.vertex_num()
    reps=[i for i in range(vnum)]
    mst,edges=[],[]
    for vi in range(vnum):
        for v,w in graph.out_edges(vi):
            edges.append((w,vi,v))
    edges.sort()
    for w,vi,vj in edges:
        if reps[vi]!=reps[vj]:
            mst.append(((vi,vj),w))
            if len(mst)==vnum-1:
                break
            rep,orep=reps[vi],reps[vj]
            for i in range(vnum):
                if reps[i]==orep:
                    reps[i]=rep
    return mst

Prim演算法 

prim演算法是MST性質的直接應用,其基本思想是:從一個頂點出發,利用MST性質選擇最短連線邊,擴充已連線的頂點集並加入所選的邊,直至結點集合裡包含了圖中的所有頂點。
演算法細節

  • 從圖G的頂點集V中任取一頂點(例如頂點v0)放人集合U中,這時U={v0},令邊集合ET={},顯然T=(U,ET)是一棵樹(只包含一個頂點且沒有邊)。
  • 檢查所有一個端點在集合U裡而另一個端點在集合V-U的邊,找出其中權最小的邊e=(u,v)(假設u\epsilon V,v\epsilon V-U),將頂點v加人頂點集合U,並將e加人邊集合。易見,擴充之後的T=(U,ET)仍是一棵樹。
  • 重複上面步驟直到U=V(所構造的樹已經包含了所有頂點)。這時集合ET裡有n-1條邊,子圖T=(U,ET),就是G的一棵最小生成樹。

下面演算法裡用了一個優先佇列cands記錄候選邊,mst的作用與前面演算法相同。開始將邊(0,0,0)壓人佇列,表示從頂點0到自身的長度為0的邊,第一個元素是權值。然後執行演算法的主迴圈,直到mst記錄了”個頂點(成功構造出最小生成樹)或優先佇列空(說明圖graph不連通,沒有最小生成樹)時結束。

#prim演算法
def Prim(graph):
    vnum=graph.vertex_num()
    mst=[None]*vnum
    cands=PrioQue([(0,0,0)])
    count=0
    while count<vnum and not cands.is_empty():
        w,u,v=cands.dequeue()
        if mst[v]:
            continue
        mst[v]=((u,v),w)
        count+=1
        for vi,w in graph.out_edges(v):
            if not mst[vi]:
                cands.enqueue((w,v,vi))
    return mst

相關推薦

小生成樹演算法(python實現)

Kruskal演算法 Kruskal演算法是一種構造最小生成樹的簡單演算法,其中的思想比較簡單。基本思想 設G=(V,E)是一個網路,其中|V|=n。Kruskal演算法構造最小生成樹的過程是: 初始時取包含G中所有n個頂點但沒有任何邊的孤立點子圖T=(V,{}),T裡的

小生成樹演算法普利姆演算法和克魯斯卡爾演算法實現

最小生成樹演算法: 普里姆演算法:頂點集合N,輔助頂點集合S,初始化中,將出發點vi加入S,並從N中刪除 1.從頂點集合N中找到一條到集合S最近的邊(vi,vj),儲存該邊,並將vj從N移到S中 2.重複1步驟直至所有頂點加入S集合 普里姆演算法:與邊的多少關係不大,適合計算邊稠密的圖

基於矩陣實現小生成樹演算法

1.最小生成樹 在Wikipedia中最小生成樹(Minimum Spanning Tree)的定義如下:A minimum spanning tree is a spanning tree of a connected, undirected graph. It conn

小生成樹演算法——Prim演算法和Kruskal演算法的JS實現

之前都是看書,大部分也是c++的實現,但是搞前端不能忘了JS啊,所以JS實現一遍這兩個經典的最小生成樹演算法。 一、權重圖和最小生成樹 權重圖:圖的邊帶權重 最小生成樹:在連通圖的所有生成樹中,所有邊的權重和最小的生成樹 本文使用的圖如下: 它的最小生成樹如下:

Prim演算法求解小生成樹的Java實現

上一篇既然提到了Krusal演算法,這裡就不得不說Prim演算法了,這兩個演算法都是求解最小生成樹的經典的貪婪演算法。與Krusal演算法不同的是,Prim演算法在求解過程中始終保持臨時結果是一顆聯通的樹。該演算法的虛擬碼如下 //假設網路中至少有一個個頂點 設T為所選邊的

資料結構基礎之圖(中):小生成樹演算法

轉自:http://www.cnblogs.com/edisonchou/p/4681602.html   圖(中):最小生成樹演算法 圖的“多對多”特性使得圖在結構設計和演算法實現上較為困難,這時就需要根據具體應用將圖轉換為不同的樹來簡化問題的求解。 一、生成樹與最小生成

關於小生成樹演算法 —— Kruskal 有效性的證明

證明過程: 首先,假設我們已經對所有邊進行了排序,並且當前遍歷到的邊是連線點1和點2的邊 因為這條邊是最小的邊,而點1和點2在最小生成樹中一定會直接或間接的相連,因此任何從點1到點2的路徑都不小於這條邊。如圖,如果不走這條邊就只能走1→3→2(而如果這樣走顯然會使得1→2的

資料結構-小生成樹演算法

最小生成樹經典演算法主要是:Prim和Kruskal演算法,其核心都是MST性質:假設G=(V,E)是一個無向連通圖,U是頂點集V的一個非空子集。若(u,v)是一條具有最小權值的邊,其中u包含於U,v包含於V,則必存在一顆包含邊(u,v)的最小生成樹。 Prim演算法:我所理解的prim的演算法

小生成樹演算法:普里姆演算法和克魯斯卡爾演算法

普里姆演算法—Prim演算法 演算法思路:  從已選頂點所關聯的未選邊中找出權重最小的邊,並且生成樹不存在環。 其中,已選頂點是構成最小生成樹的結點,未選邊是不屬於生成樹中的邊。 (普里姆演算法與求最短路徑的迪傑斯塔拉演算法思想很類似)   下面我們對下面這幅

資料結構中排序、查詢、小生成樹演算法總結

1.排序演算法 定義:把一個無序元素序列按照元素的關鍵字遞增或遞減排列為有序的序列 一、插入排序 1)直接插入排序: 基本思想:假設前i-1個元素已經有序,將第i個元素的關鍵字與前i-1個元素的關鍵 字進行比較,找到合適的位置,將第i個元素插入。按照類似的方法

關於小生成樹演算法原理的一點思考

學最小生成樹的時候一直有很多疑問: 比如克魯斯卡爾演算法:為啥不能有迴路?為啥從最小的邊開始找? 比如普利姆演算法:隨意選起點不會影響結果麼?起點選的那條最短邊就一定是最小樹上的? 一、克魯斯卡爾演算法思考 1. 為啥不能有迴路? 原因1:如果有迴

小生成樹演算法之Kruskal演算法

最近做大題目主要運用的都是資料結構方面的題,既有之前的最短路徑的相關的演算法,也有現在的最小生成樹,這裡先講解Kruskal演算法,主要是我先在剛會這個,prim演算法,明天再看。 Kruskal演算法演算法其實和之前的djs演算法有點類似,主要還是每次迴圈找出

小生成樹演算法-Prim演算法

從任意一個頂點開始構造生成樹,假設從0號頂點開始。首先將頂點0加入到生成樹中,用一個一維陣列book標記哪些頂點已經加入到生成樹。 用一個數組dis記錄生成樹到各個頂點的距離。最初生成樹中只有0號頂點,當其餘頂點與0號頂點有直連邊時,陣列dis中儲存的就是0號頂點到該頂點的

使用Matlab完成層次聚類演算法小生成樹演算法

最近要寫作業,涉及到一些聚類演算法。 關於聚類演算法的一些理論和定義,請參照部落格http://blog.sina.com.cn/s/blog_62f3c4ef01014uhe.html  和大傳送術http://blog.csdn.net/a1b2c3d4123456/a

prim小生成樹演算法原理

prim 最小生成樹演算法原理 主要需要了解演算法的原理、演算法複雜度、優缺點 、刻畫和度量指標 評價等 可以查閱相關的文獻,這部分內容主要整合了兩篇部落格的內容 分別是:http://blog.csdn.net/tham_/article/details/460489

小生成樹演算法的兩個重要屬性Cycle Property和Partition Property

Cycle Property: T是一個帶權圖的一個最小生成樹,如果存在一條邊e後,在T中形成了一個環C。 則e必須比這個環中任何一條邊都大。 證明: 反證法:如果存在一條邊比e大,則去掉這條邊,加入e後,得到的新的最小生成樹的權重 比T還要小,矛盾。 Partitio

資料結構基礎溫故-5.圖(中):小生成樹演算法

圖的“多對多”特性使得圖在結構設計和演算法實現上較為困難,這時就需要根據具體應用將圖轉換為不同的樹來簡化問題的求解。 一、生成樹與最小生成樹 1.1 生成樹   對於一個無向圖,含有連通圖全部頂點的一個極小連通子圖成為生成樹(Spanning Tree)。其本質就是從連通圖任一頂點出發進行遍歷操作所經過

小生成樹及其基本實現

最小生成樹(MST Minimum Spanning Tree):用最少的邊連線了所有的頂點。 最小生成樹邊的數量總比頂點V的數量小1. 即 E = V -1; 建立最小生成樹的演算法與搜尋演算法幾乎是相同的。它同樣可以基於廣度優先搜尋或者

Kruskal演算法小生成樹-演算法設計與分析實驗3

題目: 求如圖所示,用kruskal演算法求下面圖的最小生成樹: 話不多說,程式如下: #include<iostream> #include<stdlib.h> #define N 7 using namespace std; typedef

小生成樹演算法程式碼

1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<iostream> 4 #define MAX_VERTEX_NUM 20 5 #define OK 1