貪心法之最小生成樹之Kruskal演算法

2021-07-05 15:51:03 字數 1680 閱讀 7151

a,實際應用:現實生活中經常需要計算某種方案的最小成本問題,比如希望利用最少量的電纜線連線一座建築物中所有的計算機;再比如希望以最小的成本連線乙個網路中的所有路由器等問題。把整個問題抽象成乙個無向圖,解決問題就是要構建一棵包含圖中所有節點的樹,並使構造出的樹的總權值最小,即求解圖的最小生成樹問題。下面將介紹用於構造該種樹的方法,kruskal演算法。

b,克魯斯卡爾(kruskal)演算法:假設無向圖中有n個節點,kruskal演算法總共選擇n-1條邊,所用的貪心法思想就是:每次從剩下的邊中選擇權重最小的邊加入到樹中,前提是新加入的邊不能與已加入的邊構成迴路(不然就不能構成一棵樹了),如果構成迴路就拋棄這條邊。

c,演算法處理過程:

1)假設g是包含n個節點的連通網;

2)首先對圖中的邊按從小到大排序儲存在陣列e中;

3)然後迴圈遍歷e中的每條邊,每次判斷改邊是否會與已加入的邊構成迴路;

4)如果不構成迴路就將邊加入樹中t中,否則拋棄,繼續判斷下一條邊;

5)直到所有邊都判斷,加入或者拋棄一次之後,演算法結束;

6)所得的樹即為最小生成樹。

值得注意的是我們如何判斷當前判斷的邊是否會與已加入的邊構成迴路,乙個解決方案就是判斷邊的兩個端點是否都在已加入的邊的端點集合當中。

下圖為kruskal演算法構造最小生成樹的過程:

d,演算法實現:

#include "iostream"

using namespace std;

#define maxvex 50//圖中最大節點數

typedef struct //定義邊的資料結構

vertextype;

typedef struct //定義鄰接矩陣的資料結構

agraph;

int main()

//kruskal演算法求解最小生成樹

//g為無向網,v用於儲存最小生成樹的邊

void kruskal(agraph *g, vertextype v)

} cout<

//用選擇排序對n條邊進行排序

void selectsort(vertextype edges, int n)

} //將最小值與第乙個元素交換位置

if(min != i)

} }

void createagraph(agraph *g)//建立圖的無向網

cout<

cout

cout/建立無向圖的邊資訊

for(int j = 0; j < anum; ++j)

//初始化vexnum和adgenum

g->vexnum = vnum;

g->adgenum = anum; }

執行結果:

e,複雜度分析

時間複雜度:

kruskal演算法的時間複雜度由排序演算法決定,若採用快排則時間複雜度為o(nlogn)。當然上述實現使用的是選擇排序,所以時間複雜度為o(n^2)。

Algorithm 最小生成樹之 Kruskal

個人觀點,較prime演算法,kurskal演算法更加的簡單,這裡我們只需要每一次去需找權值最小的那條邊就好,在這裡我們先可以利用sort進行快排,得到權值最小的map i 得到該條邊的兩個節點map i u 和map i v,這時候你需要判斷能不能用這條邊,因為最小生成樹是不能形成迴路,所以用到了...

貪心法實現Prim最小生成樹(java)

設最小生成樹的節點的集合為u 候選集 待加入最小生成樹的節點的集合 割 邊 候選集中節點與u中節點的連線形成的邊為割邊 class ttreeedge 儲存邊資訊 起始點,終止點,權值 public class prim int i,j,k tcloserec close new tcloserec...

貪心演算法之最小生成樹(Prim)

最小生成樹 prim 網路的生成樹中的邊帶權值,將生成樹各邊的權值加起來稱為生成樹的權,權值最小的生成樹稱為為最小生成樹。設g v,e 是連通帶權圖,v prim演算法基本思想 首先置s 然後,只要s是v的真子集,就進行如下貪心選擇 選取滿足條件i s,j v s,且c i j 最小的邊,將頂點j新...