最小生成樹-Kruskal算法-python

圖的基本概念:

  1. :圖由頂點集V和邊集E組成,表示爲G=(V,E);
  2. 邊權:邊e具有權重,(結合不同環境具體可以理解爲兩點的距離、相似度)
  3. :任意兩點都有路徑相連,但是沒有迴路
  4. 最小生成樹(MST:minimum spanning tree):邊權之和最小的樹,n個頂點產生(n-1)個邊

Kruskal算法原理:

  1. 將邊按權重從小到大進行排序;
  2. 將每個頂點獨立視爲根節點,產生n個樹;
  3. 依次選取每條邊,如果邊的兩個頂點不屬於同一個樹,則將其合併,如果屬於同一個樹(意味着會形成迴路),則將其捨棄,考慮下一條邊,最後形成(n-1)條邊

Kruskal算法解析

圖1由頂點集{‘A’,‘B’,‘C’,‘D’,‘E’,‘F’,‘G’}和一系列帶有權重的邊組成(本質上n個頂點兩兩相連可以形成n(n-1)/2條邊,圖中省略部分邊及邊權)

圖1

將7個頂點視爲7個樹的根節點。首先選取權重最小的邊e(BF),其頂點爲B、F,兩點不屬於同一棵樹,故合併。

圖2

然後選取權重爲3的邊e(CD),兩點也不屬於同一棵樹,故合併。

圖3

重複上述步驟,依此得到:

圖4
圖5

 

圖6

 

當選取到權重爲6的邊e(EF)時,發現頂點E,F同屬於一棵樹,故舍棄,最後最小生成樹有兩種情況,如圖7,圖8

圖7
圖8

實操

1.定義頂點

vertices=list('ABCDEFG')

2.定義邊並按邊權進行排序

edges = [("A", "B", 5), ("A", "G", 7),
         ("B", "F", 1), ("C", "F", 4),
         ("C", "D", 3), ("C", "E", 7),
         ("E", "F", 6), ("D", "E", 4),
         ("E", "G", 12),("F", "G", 12)]
edges.sort(key=lambda x:x[2])
print(edges)

輸出如下:

3.將每個頂點視爲一棵節點樹,可以用字典表示,鍵表示頂點,鍵值表示頂點所在樹的節點

ori_trees=dict()
for i in vertices:
    ori_trees[i]=i
print(ori_trees)

輸出爲:

4.根據邊的兩個頂點的根節點是否相同考慮是否合併

#尋找根節點
def find_node(x):
    if ori_trees[x]!=x:
        ori_trees[x]=find_node(ori_trees[x])
    return ori_trees[x]
#定義最小生成樹
mst=[]
#定義循環次數,n爲需要添加的邊數=頂點數-1
n=len(vertices)-1
#循環
for edge in edges:
    v1,v2,_=edge
    if find_node(v1)!=find_node(v2):
        ori_trees[find_node(v2)]=find_node(v1)
        mst.append(edge)
        print('添加第'+str(7-n)+'條邊後:')
        n-=1
        print(ori_trees)
        print(mst)
        if n==0:
            break

輸出結果如下:

完整代碼如下:

 

edges = [("A", "B", 5), ("A", "G", 7),
         ("B", "F", 1), ("C", "F", 4),
         ("C", "D", 3), ("C", "E", 7),
         ("E", "F", 6), ("D", "E", 4),
         ("E", "G", 12),("F", "G", 12)]
vertices=list('ABCDEFG')
edges.sort(key=lambda x:x[2])
ori_trees=dict()
for i in vertices:
    ori_trees[i]=i
#尋找根節點
def find_node(x):
    if ori_trees[x]!=x:
        ori_trees[x]=find_node(ori_trees[x])
    return ori_trees[x]
#定義最小生成樹
mst=[]
#定義循環次數,n爲需要添加的邊數=頂點數-1
n=len(vertices)-1
#循環
for edge in edges:
    v1,v2,_=edge
    if find_node(v1)!=find_node(v2):
        ori_trees[find_node(v2)]=find_node(v1)
        mst.append(edge)
        print('添加第'+str(7-n)+'條邊後:')
        n-=1
        print(ori_trees)
        print(mst)
        if n==0:
            break

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章