最小生成樹 Prim演算法

2021-08-02 17:26:06 字數 3377 閱讀 4139

生成樹

生成樹是連通圖的最小連通子圖。所謂最小是指:若在樹中任意增加一條邊,則將出現乙個迴路;若去掉一條邊,將會使之變成非連通圖。按照該定義,n個頂點的連通網路的生成樹有n個頂點,n-1條邊

可知用不同的遍歷圖的方法,可以得到不同的生成樹;從不同的頂點出發,也可能得到不同的生成樹。

最小生成樹

生成樹各邊的權值總和稱為生成樹的權,權最小的生成樹稱為最小生成樹

常見的構造最小生成樹的方法有prim演算法和kruskal演算法。

下面介紹prim演算法

prim演算法

prim演算法通常以鄰接矩陣作為儲存結構。

它的基本思想是以頂點為主導地位,從起始頂點出發,通過選擇當前可用的最小權值邊把頂點加入到生成樹當中來

1.從連通網路n=中的某一頂點u0出發,選擇與它關聯的具有最小權值的邊(u0,v),將其頂點加入到生成樹的頂點集合u中。

2.以後每一步從乙個頂點在u中,而另乙個頂點不在u中的各條邊中選擇權值最小的邊(u,v),把它的頂點加入到集合u中。如此繼續下去,直到網路中的所有頂點都加入到生成樹頂點集合u中為止。 

可行性證明:

設prim生成的樹為g0

假設存在gmin使得cost(gmin)0)

則在gmin中存在(u,v)不屬於g0

將(u,v)加入g0中可得乙個環,且(u,v)不是該環的最長邊

這與prim每次生成最短邊矛盾

故假設不成立,得證.

下面看具體資料和模擬過程

現在有乙個儲存結構為鄰接矩陣的g,有9個頂點,它的arc二維陣列如上圖所示。

於是prim演算法的**如下,其中infinity為權值極大值,不妨設為0xfffffff,maxvex為頂點個數最大值,此處大於等於9即可。

void minspantree_prim(mgraph g)

,而adjvex則全部為0。此時,已經完成了整個初始化的工作,準備開始生成。

4.第13~35行,整個迴圈過程就是構造最小生成樹的過程。

5.第14~16行,將min設定為了乙個極大值0x3fffffff,它的目的是為了之後找到一定範圍內的最小權值。j是用來做頂點下標迴圈的變數,k是用來儲存最小權值的頂點下標。

6. 第17~24行,迴圈中不斷修改min為當前lowcost陣列中最小值,並用k保留此最小值的頂點下標。經過迴圈後,min=10,k=1。第19行if判斷的lowcost[j]!=0表示已經是生成樹的頂點不參與最小權值的查詢

7.第25行,因k=1,adjvex[1]=0,所以列印結果為(0,1),表示v0至v1邊為最小生成樹的第一條邊。如下圖所示:

8.第26行,此時因k=1,我們將lowcost[k]=0就是說頂點v1納入到最小生成樹中。此時lowcost陣列值為。

9.第27~33行,j迴圈由1至8,因k=1,查詢鄰接矩陣的第v1行的各個權值,與lowcost的對應值比較,若更小則修改lowcost值,並將k值存入adjvex陣列中。因第v1行有18、16、12均比0x3fffffff小,所以最終lowcost陣列的值為:。adjvex陣列的值為:。這裡第30行if判斷的lowcost[j]!=0也說明v0和v1已經是生成樹的頂點不參與最小權值的對比了

10.再次迴圈,由第14行到25行,此時min=11,k=5,adjvex[5]=0。因此列印結構為(0,5)。表示v0至v5邊為最小生成樹的第二條邊,如下圖所示:

11.接下來執行到33行,lowcost陣列的值為:。adjvex陣列的值為:。

12.之後經過類似的模擬,如下圖:

總結使用鄰接矩陣作為儲存結構的prim演算法的時間複雜度為o(v2),如果使用二叉堆與鄰接表表示的話,prim演算法的時間複雜度可縮減為o(e log v),其中e為連通圖的邊數,v為頂點數。

如果使用較複雜的斐波那契堆,則可將執行時間進一步縮短為o(e + v log v),這在連通圖足夠密集時(邊較多,即e滿足ω(v log v))可較顯著地提高執行速度。

求minispan_tree中longest edge

vector中存每個點所連邊的序號 通過邊集陣列索引

//求minispan_tree中longest edge

//o(n^2)

//vector中存每個點所連邊的序號 通過邊集陣列索引

#include#include#includeusing namespace std;

struct edge

};const int maxn=10010;

const int inf=0x3f3f3f3f;

int ans;

vectoredges;

vectorg[maxn];

int n,m;

void addedge(int u,int v,int w)

int adjvex[maxn];//最小生成樹上每個點的前驅

int lowcost[maxn];//前驅到這個點的距離,即目前最小生成樹中到該點的最短距離

bool v[maxn];//是否在生成樹中的標記

void prim()

int adjvex[maxn];//最小生成樹上每個點的前驅

int lowcost[maxn];//前驅到這個點的距離

int v[maxn];//是否在生成樹中的標記

void prim()

{    for(int i=1;i<=n;++i) lowcost[i]=inf;

lowcost[1]=0;

for(int i=1;i<=n;++i) adjvex[i]=0,v[i]=0;

adjvex[1]=1;

for(int i=1;i<=n;++i){

//for(int i=1;i<=n;++i) cout<

最小生成樹(prim演算法)

最小生成樹是資料結構中圖的一種重要應用,它的要求是從乙個帶權無向完全圖中選擇n 1條邊並使這個圖仍然連通 也即得到了一棵生成樹 同時還要考慮使樹的權最小。prim演算法要點 設圖g v,e 其生成樹的頂點集合為u。把v0放入u。在所有u u,v v u的邊 u,v e中找一條最小權值的邊,加入生成樹...

最小生成樹 Prim演算法

prim 演算法 以領接矩陣儲存 圖g bool b i 表示頂點i是否被訪問,初始化時候memset b,false,sizeof b b 0 value,表示從第0個節點開始。用value i 表示節點i到最小生成樹a中定點的最小距離。例如value 1 a 0 1 int sum記錄權值和 i...

最小生成樹 prim 演算法

一 演算法描述 假設存在連通帶權圖g v,e 其中最小生成樹為t,首先從圖中隨意選擇一點s屬於v作為起始點,並將其標記後加入集合u 中。然後演算法重複執行操作為在所有v屬於u,u屬於v u的邊 v0,u0 屬於e中找一條代價最小的邊並加入集合t,同時將u0併入u,直到u v為止。這是,t中必有n 1...