資料結構之最小生成樹

2021-06-22 09:46:41 字數 3270 閱讀 7844

最小生成樹: 乙個連通圖的生成樹是乙個極小連通子圖,它含有圖中全部頂點,但只有足以構成一棵樹的n-1條邊。這種構造連通網的最小代價生成樹稱為最小生成樹,詳見資料結構之圖(術語、儲存結構、遍歷)

。求連通網的最小生成樹有兩種經典方法:普里姆(prime)演算法和克魯斯卡爾(kruskal)演算法。

假設n=(v,)是連通網,te是n上最小生成樹中邊的集合。從v中任選乙個頂點u0,演算法從u=(u0∈v),te={}開始,重複執行以下步驟:

在所有u∈u、v∈v-u的邊(u, v)∈e中找一條代價最小的邊(u, vi)併入集合te,同時將vi併入u,直至u=v為止。

此時te中必有n-1條邊,則t=}即為n的最小生成樹。

需要用到兩個輔助陣列:

lowcost[max_vem]:儲存從u到v-u的具有最小代價邊上的權——lowcost[i] = min

adjvex[max_vem]:儲存從u到v-u的具有最小代價邊(u,vi)依附在u中的頂點u的下標——adjvex[i] =

給定如下乙個無向網:

根據上述prime演算法描述,求其最小生成樹的過程如下:

最後得到如下最小生成樹:

//普里姆(prime)演算法

void minispantree_prime(graph *g, vertextype u0)

} int lowcost[max_vex]; //儲存從u到v-u的具有最小代價邊上的權——lowcost[i] = min

v0 = k = locatevex(g, u0); //定位開始的頂點u0在頂點陣列中的下標號

assert(k != -1);

//adjvex[k] = k; //初始化第乙個頂點下標為k

lowcost[k] = 0; //初始,u=

for (i = 0; i < g->vexnum; i++) }

for (i = 0; i < g->vexnum; i++)

min = infinity;

for (j = 0, k = 0; j < g->vexnum; j++)

}//printf("(%d,%d) ", adjvex[k], k); //列印當前頂點中權值最小的邊:

//g->vexs[adjvex[k]]∈u,g->vexs[k]∈v-u

printf("(%c,%c) ", g->vexs[adjvex[k]], g->vexs[k]);

lowcost[k] = 0; //第k頂點併入u集

for (j = 0; j < g->vexnum; j++)

}} putchar('\n');

}

執行截圖:

分析:鄰接矩陣實現的普里姆演算法的時間複雜度為o(n^2),與網中的邊數無關,適用於求邊稠密的網的最小生成樹。

假設連通網n=},令最小生成樹的初始狀態為只有n個頂點而無邊的非連通圖t=},圖中的每個頂點自成乙個連通分量。在e中選擇代價最小的邊,若改邊依附的頂點落在t中不同的連通分量上,則將次邊加入到t中,否則捨去此邊而選擇下一條代價i最小的邊。以此類推,直到t中所有頂點都在同乙個連通分量上為止。

kruskal演算法主要考慮是否會形成環路。在實際的**編寫中,一般採用邊集陣列這一資料結構:

//邊集陣列

#define max_edge 100 //最大邊數

typedef struct

edge;

我們可以通過程式將鄰接矩陣通過程式轉化為邊集陣列,並且對它們的按權值從小到大排序。如下圖所示。

//將鄰接矩陣結構轉化成邊集

void convert(graph *g, edge edge)

#if 0

printf("排序前:\n");

printf(" \tbeign\tend\tweight\n");

for(i = 0; i < k; i++)

#endif

insertsort(edge, k);

#if 1

printf("排序後:\n");

printf(" \tbeign\tend\tweight\n");

for(i = 0; i < k; i++)

#endif

}//按權值大小對邊集陣列edge從小至大排序

void insertsort(edge edge, int k)

edge[j + 1] = tmp;

} }}//查詢連線頂點的尾部

int find(int *parent, int f)

return f;

}//克魯斯卡爾演算法實現

void minispantree_kruskal(graph *g)

for(i = 0; i < g->arcnum; i++) //迴圈每一條邊 }

putchar('\n');

}

執行截圖:

不考慮鄰接矩陣或鄰接表轉化為邊集陣列的時間開銷,克魯斯卡爾演算法的find函式由邊數e決定,時間複雜度為o(loge),而外面有乙個for迴圈e次,所以克魯斯卡爾演算法的時間複雜度為o(eloge),相對prime演算法而言,適合於求邊稀疏的網的最小生成樹。

參考:這篇文章的url提示不對呀 「** 文章包含被禁用的url,無法儲存和發布。」 ,沒法給出參考鏈結了

資料結構(c語言版)

完整的測試**:

C 資料結構之最小生成樹

最小生成樹是圖的一部分,一般求最小生成樹用prim演算法和kruskal演算法。對於prim演算法,思想是 在訪問過的頂點和未訪問的頂點之間選擇權值最小的邊。prim演算法是基於頂點的操作,適合於頂點較少,邊較多的圖。對於kruskal演算法,思想是 直接從圖中選擇權值最小的邊,並且已選擇的邊不能構...

資料結構 最小生成樹

生成樹 乙個連通圖的最小連通子圖稱作該圖的生成樹。有n個結點的連通圖的生成樹有n個結點和n 1條邊。乙個有n個結點的連通圖的生成樹是原圖的極小連通子圖,它包含原圖中的所有n個結點,並且有保持圖連通的最少的邊。由生成樹的定義可知 若在生成樹中刪除一條邊,就會使該生成樹因變成非連通圖而不再滿足生成樹的定...

資料結構(最小生成樹)

對於乙個無相連通網,他的所有生成樹中必有一棵邊的權值總和最小的生成樹,稱之為最小代價生成樹,簡稱最小生成樹。最小生成樹必須滿足三個條件 1 構造的最小生成樹必須包括n個頂點 2 構造的最小生成樹有且僅有n 1條邊 3 構造的最小生成樹中不存在迴路。普利姆演算法 prim 假設g v,e 為一無向連通...