《演算法導論》第23章 最小生成樹

2021-08-31 11:37:16 字數 3949 閱讀 9816

在上圖中,就是邊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演算法屬於貪心演算法,與廣度優先搜尋類似。保持乙個屬於已發現的最小生成樹節點的集合。每一次從未在樹中的節點中選擇乙個與...