最小生成樹之kruskal演算法

2022-06-29 03:09:11 字數 2386 閱讀 1589

最小生成樹之kruskal演算法

1.kruskal演算法

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

示例如下:

圖中先將每個頂點看作獨立的子圖,然後查詢最小權值邊,這條邊是有限制條件的,邊得兩個頂點必須不在同乙個圖中,如上圖,第乙個圖中找到最小權值邊為(v1,v3),且滿足限制條件,繼續查詢到邊(v4,v6),(v2,v5),(v3,v6),當查詢到最後一條邊時,僅僅只有(v2,v3)滿足限制條件,其他的如(v3,v4),(v1,v4)都在乙個子圖裡面,不滿足條件,至此已經找到最小生成樹的所有邊。

2.kruskal演算法

程式設計

由於我們要查詢邊權值最小的邊,那麼我們的第一步應該把邊權值排序,這樣就可以很快查詢到權值最小的邊,為了簡化程式設計,我們不使用其他的資料結構,僅僅設立乙個結構體陣列來儲存邊,用乙個標記陣列來標記哪些邊已經被選擇(實際程式設計的時候沒有用到標記陣列);

解決了邊得儲存和排序問題,現在是演算法最關鍵的就是怎麼判斷邊的兩個頂點不在乙個子圖裡面,乙個簡單的辦法是設立乙個輔助陣列f[n],初始化如下:

void 

initialize

()如此初始化是為了讓每個頂點各自為乙個圖,如果找到一條邊(i,j)那麼做如下標記:(i

void mark_same(int i, int j)

f[j] = i;//將j指向其父節點

}上面的標記過程也給了我們怎麼判斷兩個頂點是否在乙個圖中找到了方法,即判斷其父節點是否相同,相同則是在乙個圖里;

int is_same(int i, int j)

//找到i的父節點

while(f[j] != j)

return i == j ? 1 : 0;

}注意:實際設計程式的時候不用標記已選邊,因為已選擇的邊會講端點集合合併為乙個集合,從而在判斷是否為同一集合的時候就可以排除了。

測試用例:

測試程式:

#include 

#include 

#define max 100

#define n 6//頂點數目 

/* 定義邊(x,y),權為w */

typedef struct

edge;

edge e[max];

/* father[x]表示x的父節點 */

int father[n];

/* 比較函式,按權值(相同則按x座標)非降序排序 */

int cmp(const void *a, const void *b)

return (*(edge *)a).w - (*(edge *)b).w;

}/* 判斷集合是否相同 */

int is_same(int i, int j)

//找到i的父節點

while(father[j] != j)

return i == j ? 1 : 0;

}/* 合併x,y所在的集合 */

void mark_same(int i, int j)

//找到i的父節點

while(father[i] != i)

father[j] = i;//將j指向其父節點

}//初始化 father陣列 

void initialize()

/* 主函式 */

int main()

/* 讀取邊資訊並初始化集合 */

while(fscanf(fr,"%d %d %d", &e[i].x, &e[i].y, &e[i].w) != eof)

i++;

/* 將邊排序 */

qsort(e, i, sizeof(edge), cmp);

initialize();

for (i = 0; i 

}system("pause");

return 0;

}程式結果:

1 34 6

2 53 6

1 42 3

請按任意鍵繼續. . .

最小生成樹之Kruskal演算法

最小生成樹 kruskal演算法描述 該演算法是基於貪心的思想得到的。首先我們把所有的邊按照權值先從小到大排列,接著按照順序選取每條邊,如果這條邊的兩個端點不屬於同一集合,那麼就將它們合併,直到所有的點都屬於同乙個集合為止。合併頂點可以利用並查集,換而言之,kruskal演算法就是基於並查集的貪心演...

最小生成樹之kruskal演算法

先構造乙個只含 n 個頂點 而邊集為空的子圖,把子圖中各個頂點看成各棵樹上的根結點,之後,從網的邊集 e 中選取一條權值最小的邊,若該條邊的兩個頂點分屬不同的樹,則將其加入子圖,即把兩棵樹合成一棵樹,反之,若該條邊的兩個頂點已落在同一棵樹上,則不可取,而應該取下一條權值最小的邊再試之。依次類推,直到...

最小生成樹之kruskal演算法

克魯斯卡爾 kruskal 演算法過程 構造最小生成樹 u,te 1.置u的初值等於v 即包含有g中的全部頂點 te的初值為空集 即圖t中每乙個頂點都構成乙個連通分量 2.將圖g中的邊按權值從小到大的順序依次選取 若選取的邊未使生成樹t形成迴路,則加入te 否則捨棄,直到te中包含 n 1 條邊為止...