最小生成樹,克魯斯卡爾算法.
算法簡述:
將每個頂點看成一個圖.
在所有圖中找權值最小的邊.將這條邊的兩個圖連成一個圖,
重復上一步.直到只剩一個圖.


注:將abcdef每個頂點看成一個圖.將最小權值的邊的兩個圖連接.
連接最小權值為1的兩個圖,這時a-c,b,d,e,f.
連接最小權值為2的兩個圖,這時a-c,b,d-f,e.
連接最小權值為3的兩個圖,這時a-c,b-e,d-f.
連接最小權值為4的兩個圖,這時a-c-f-d,b-e.(c-f)
連接最小權值為5的兩個圖,這時a-c-b-e-f-d.(b-c)
結束.
根據上述操作,我們需要一個存儲邊信息的數組(Edge結構體),Edge包含了邊的兩個節點和權值.
1 typedef struct 2 { 3 int head;//邊的始點下標 4 int tail;//邊的終點下標 5 int power;//邊的權值 6 } Edge;
還需要一個visited數組,用來標識圖中的節點信息.
算法操作:
初始化一棵樹(用來保存最小生成樹,直接輸出也行.)
將圖中所有邊復制到一個數組中,將數組排序(遞增順序)
將小邊的兩個頂點連接.將兩個圖合並成一個圖.
重復上一步.
臨街矩陣的代碼實現
代碼中,ijk做循環用,v1,v2做邊的兩個頂點信息的下標,vs1,vs2做標識v1和v2所屬圖
1-27行,初始化visited,edge,kruskal_tree等信息.
29-44行,生成一棵最小生成樹.
35行,if是為了防止回路,vs1和vs2標識一個這兩點是否屬於一個圖.
38行,for是為了將visited數組中vs2邊成vs1,因為這時,v1和v2已經在一個圖里了.
1 void kruskal(Graph * graph, Graph * kruskal_tree) 2 { 3 int visited[graph->vertexs]; 4 Edge edge[graph->brim]; 5 int i, j, k; 6 int v1, v2, vs1, vs2; 7 8 for ( i = 0; i < graph->vertexs; i++ ) 9 visited[i] = i; 10 11 k = 0; 12 for ( i = 0; i < graph->vertexs; i++ ) 13 { 14 for ( j = i + 1; j < graph->vertexs; j++ ) 15 { 16 if ( graph->arcs[i][j] != MAX_VALUE ) 17 { 18 edge[k].head = i; 19 edge[k].tail = j; 20 edge[k].power = graph->arcs[i][j]; 21 k++; 22 } 23 } 24 } 25 26 init_kruskal(graph, kruskal_tree); 27 my_sort(edge, graph->brim); 28 29 for ( i = 0; i < graph->brim; i++ ) 30 { 31 v1 = edge[i].head; 32 v2 = edge[i].tail; 33 vs1 = visited[v1]; 34 vs2 = visited[v2]; 35 if ( vs1 != vs2 ) 36 { 37 kruskal_tree->arcs[v1][v2] = graph->arcs[v1][v2]; 38 for ( j = 0; j < graph->vertexs; j++ ) 39 { 40 if ( visited[j] == vs2 ) 41 visited[j] = vs1; 42 } 43 } 44 } 45 }
臨街矩陣源碼:http://www.cnblogs.com/ITgaozy/p/5200637.html
鄰接表的代碼實現
17行,if是為了將防止邊的重復輸入(在鄰接矩陣中,點在矩陣中是對稱的,所以我們只輸入一個上三角中的數據就夠了.但在鄰接表中,我們如何判斷一條邊是否已經輸入過了? 我的方法是將比當前節點下標大的輸入,例如右a,b兩個節點,a的節點小與b,我們在輸入b的信息時,由於a的節點下標比b小,不輸入a-b這條邊,因為我們在輸入a的信息時,a-b這條邊已經輸入過了.
1 void kruskal(Graph * graph, Graph * kruskal_tree) 2 { 3 int visited[graph->vertexs]; 4 int i, j; 5 Edge edge[graph->brim]; 6 int v1, v2, vs1, vs2; 7 Arc_node * cur, * tmp; 8 9 for ( i = 0; i < graph->vertexs; i++ ) 10 visited[i] = i; 11 12 for ( i = 0, j = 0; i < graph->vertexs; i++ ) 13 { 14 cur = graph->adjlist[i].next; 15 while ( cur != NULL ) 16 { 17 if ( cur->pos > i ) 18 { 19 edge[j].head = i; 20 edge[j].tail = cur->pos; 21 edge[j].power = cur->distance; 22 j++; 23 } 24 cur = cur->next; 25 } 26 } 27 28 init_kruskal(graph, kruskal_tree); 29 my_sort(edge, graph->brim); 30 31 for ( i = 0; i < graph->brim; i += 1 ) 32 { 33 v1 = edge[i].head; 34 v2 = edge[i].tail; 35 vs1 = visited[v1]; 36 vs2 = visited[v2]; 37 if ( vs1 != vs2 ) 38 { 39 if ( kruskal_tree->adjlist[v1].next == NULL ) 40 { 41 kruskal_tree->adjlist[v1].next = make_node(v2, edge[i].power); 42 } 43 else 44 { 45 tmp = kruskal_tree->adjlist[v1].next; 46 while ( tmp->next != NULL ) 47 tmp = tmp->next; 48 tmp->next = make_node(v2, edge[i].power); 49 } 50 for ( j = 0; j < graph->vertexs; j++ ) 51 { 52 if ( visited[j] == vs2 ) 53 visited[j] = vs1; 54 } 55 } 56 } 57 }
鄰接表源碼:http://www.cnblogs.com/ITgaozy/p/5200643.html
