在上圖中,就是邊cd。
這兩個定理看不懂沒關係,不影響後面學習kruskal演算法與prim演算法。
kruskal演算法
我的理解:
1、尋找權值最小的邊,如果邊的兩個頂點屬於不同的集合就加入到a
2、重複過程1,直到找到n-1條邊
第一點中分集合的方法我借鑑了wxdjss的部落格,以下是他的部落格鏈結
方法就是一開始的時候給每棵樹都規定乙個int,這是它所在的集合,如果找到同伴了,也就是說比如ab邊要加入到a中了,那麼檢索所有的點的int,如果它在集合和a中(也就是這個點的int==a的int),那麼就讓這顆點的int=b的int,也就是說都加入到b的集合中了。
我寫的**的思路:
1、給每個點分配乙個集合,點的屬性mark表示在第mark個集合中
2、邊從小排到大,依次遍歷,如果起點與終點的mark不同(不在同一棵樹中),把這條邊加入到a中,同時修改起點與終點所在的樹的mark,讓它們都統一(遍歷每個點,所有與起點mark相同的,就賦值為終點的mark)
3、如果a滿了,就結束迴圈
prim演算法
我寫的**的思路:
1、建立乙個陣列a用來存放已經加入的邊
2、每個頂點有乙個belong標誌著在結合a中(true)還是不在(false)
3、每條邊有乙個mark標誌著是否在集合a中
4、把邊從小排到大,遍歷每條邊,如果不在集合中,如果起點與終點的belong屬性不同(表示這條邊跨集合),那就把這條邊加入到集合a中
5、如果集合a滿了(已經有8條邊了),結束迴圈
kruskal.h
#pragma once
#define kruv 9/*點的數量*/
#define krue 14/*邊的數量*/
/*頂點*/
typedef struct
kruv;
/*邊*/
typedef struct
krue;
typedef struct
krug;
bool cmp(krue* x, krue* y);
/*kruskal演算法*/
void mst_kruskal(krug* &g);
/*列印邊*/
void printkru();
/*測試函式*/
void testkru();
kruskal.cpp
#include "kruskal.h"
#include#include#include/*sort排序函式所需標頭檔案*/
#includeusing namespace std;
krue* a[kruv];/*最小生成樹的邊集*/
/*排序*/
bool cmp(krue* x, krue* y)
/*kruskal演算法*/
void mst_kruskal(krug* &g)
else
i++;/*掃瞄下一條邊*/ }}
/*列印邊*/
void printkru()
cout << "總權重:" << weight;
cout << endl;
}/*測試函式*/
void testkru()
主函式
#include "kruskal.h"
#include int main()
執行結果這邊顯示了邊加入的順序
prim.h
#pragma once
#define primv 9/*點的數量*/
#define prime 14/*邊的數量*/
/*點*/
typedef struct
primv;
/*邊*/
typedef struct
prime;
/*圖*/
typedef struct
primg;
/*排序函式*/
bool primcmp(prime* x, prime* y);
/*prim演算法*/
void mst_prim(primg* &g, primv* root);
/*列印邊*/
void prim_print();
/*測試函式*/
void testprim();
prim.cpp
#include "prim.h"
#include#include#include/*sort排序函式所需標頭檔案*/
#includeusing namespace std;
prime* prima[primv-1];/*最小生成樹的邊集*/
/*排序函式*/
bool primcmp(prime* x, prime* y)
/*prim演算法*/
void mst_prim(primg* &g,primv* root)
root->belong = true;/*把根放到a裡面*/
for (i = 0; i < prime; i++)/*對每條邊進行初始化,q集合是圖中的集合減去a,這裡沒有明示*/
sort(g->e, g->e + prime, primcmp);/*按權重對邊進行從小到大的排序*/
j = 0;
while (j < primv - 1)/*當集合a沒有滿*/
}} }
}/*列印邊*/
void prim_print()
cout << "總權重:" << weight;
cout << endl;
}/*測試函式*/
void testprim()
主函式
#include "prim.h"
#include int main()
執行結果這邊顯示了邊加入的順序:
參考文章及部落格:
wxdjss的部落格
演算法導論 第23章 最小生成樹
最小生成樹 minimum spanning tree 全稱 最小權值生成樹 在含有n個頂點的連通圖中選擇n 1條邊,構成一棵極小連通子圖,並使該連通子圖中n 1條邊上權值之和達到最小,則稱其為連通網的最小生成樹。有兩種具體的實現演算法 kruskal演算法 prim演算法 兩者都用到了貪心演算法。...
最小生成樹(演算法導論第23章)
下面討論的兩種最小生成樹演算法都是貪心演算法。貪心演算法的每一步必須在多個可能的選擇中選擇一種,貪心演算法選擇在當前看來最好的選擇。通用演算法是每個時刻生長最小生成樹的一條邊 安全邊 並在整個策略的實施過程中,管理乙個遵守下述迴圈不變式的邊集合a 在每遍迴圈之前,a是某棵最小生成樹的子集。gener...
演算法導論 最小生成樹
華電北風吹 日期 2016 1 16 常用的最小生成樹演算法有prime演算法和kruskal演算法。prime演算法基於節點,kruskal基於邊。1 prime演算法 prime演算法屬於貪心演算法,與廣度優先搜尋類似。保持乙個屬於已發現的最小生成樹節點的集合。每一次從未在樹中的節點中選擇乙個與...