用C++分别实现了Kruskal和Boruvka算法计算MST
其中Kruskal算法中对边的排序用的heapsort
#include#include #include using namespace std; struct Edge { int src; int dest; int weight; Edge() = default; Edge(int s, int d, int w) : src(s), dest(d), weight(w) {}; }; struct Graph { int V; // number of vertices int E; // number of edges vector edges; // edges start from index 1 }; struct subset { int parent; int rank; }; bool operator<(const Edge &lhs, const Edge &rhs) { return lhs.weight < rhs.weight; } bool operator<=(const Edge &lhs, const Edge &rhs) { return lhs.weight <= rhs.weight; } void max_heapfy(vector &arry, size_t pos, size_t n) { auto child = pos * 2; while (child <= n) { if (child < n && arry[child] < arry[child + 1]) ++child; if (arry[pos] <= arry[child]) { swap(arry[pos], arry[child]); pos = child; } else break; child = pos * 2; } } void build_heap(vector &arry) { auto n = arry.size() - 1; for (auto i = n / 2; i >= 1; --i) max_heapfy(arry, i, n); } void heap_sort(vector &arry) { auto n = arry.size() - 1; build_heap(arry); for (vector ::size_type i = n; i >= 2; --i) { swap(arry[1], arry[i]); max_heapfy(arry, 1, i - 1); } } // union-find data structure // use path compression techinique int find(vector &subsets, int i) { if (subsets[i].parent != i) find(subsets, subsets[i].parent); return subsets[i].parent; } void Union(vector &subsets, int i, int j) { int iroot = find(subsets, i); int jroot = find(subsets, j); // union by rank; if (subsets[iroot].rank < subsets[jroot].rank) subsets[iroot].parent = jroot; if (subsets[iroot].rank > subsets[jroot].rank) subsets[jroot].parent = iroot; if (subsets[iroot].rank == subsets[jroot].rank) { ++subsets[iroot].rank; subsets[jroot].parent = iroot; } } // build graph from matrix to Graph void buildGraph(vector > &graph, Graph &ret) { ret.V = static_cast (graph.size()); ret.E = 0; ret.edges.push_back(Edge(INT_MAX, INT_MAX, INT_MAX)); // edge index starts from 1 for (int i = 0; i < ret.V; ++i) { for (int j = 0; j < ret.V; ++j) { if (graph[i][j] > 0) { ++ret.E; ret.edges.push_back(Edge(i, j, graph[i][j])); graph[j][i] = 0; } } } } // judge whether exists cycle bool isCycle(Graph &graph) { int V = graph.V; int E = graph.E; vector subsets(V); for (int i = 0; i < V; ++i) { subsets[i].parent = i; subsets[i].rank = 0; } for (int i = 1; i <= E; ++i) { int src_root = find(subsets, graph.edges[i].src); int dest_root = find(subsets, graph.edges[i].dest); if (src_root == dest_root) return true; Union(subsets, src_root, dest_root); } return false; } // kruskal algorithm vector KruskalMST(vector > &matrix) { vector ret; Graph graph; buildGraph(matrix, graph); heap_sort(graph.edges); vector subsets(graph.V); for (int i = 0; i < graph.V; ++i) { subsets[i].parent = i; subsets[i].rank = 0; } for (int i = 1; i < graph.edges.size(); ++i) { int src = graph.edges[i].src; int dest = graph.edges[i].dest; if (find(subsets, src) != find(subsets, dest)) { ret.push_back(graph.edges[i]); Union(subsets, src, dest); } } return ret; } vector BoruvkaMST(vector > &matrix) { vector ret; Graph graph; buildGraph(matrix, graph); vector dist(graph.V, -1); // minimum edge for every component, this stores edges's indexes vector subsets(graph.V); for (int i = 0; i < graph.V; ++i) { subsets[i].parent = i; subsets[i].rank = 0; } int v = graph.V; while (v > 1) { for (int i = 1; i < graph.edges.size(); ++i) { int set1 = find(subsets, graph.edges[i].src); int set2 = find(subsets, graph.edges[i].dest); if (set1 == set2) continue; if (dist[set1] == -1 || graph.edges[dist[set1]].weight > graph.edges[i].weight) // check set1's minimum edge with i th edge dist[set1] = i; if (dist[set2] == -1 || graph.edges[dist[set2]].weight > graph.edges[i].weight) // check set2's minimum edge with i th edge dist[set2] = i; } for (int i = 0; i < dist.size(); ++i) { if (dist[i] != -1) { int set1 = find(subsets, graph.edges[dist[i]].src); int set2 = find(subsets, graph.edges[dist[i]].dest); if (set1 == set2) continue; ret.push_back(graph.edges[dist[i]]); Union(subsets, set1, set2); --v; } } } return ret; } int main(int argc, const char * argv[]) { vector > g = { { 0, 2, 0, 6, 0 },{ 2, 0, 3, 8, 5 },{ 0, 3, 0, 0, 7 },{ 6, 8, 0, 0, 9 },{ 0, 5, 7, 9, 0 } }; auto ret = BoruvkaMST(g); for (auto a : ret) cout << a.src << " to " << a.dest << endl; cout << "-------------------------------" << endl; auto ret2 = KruskalMST(g); for (auto a : ret2) cout << a.src << " to " << a.dest << endl; system("PAUSE"); return 0; }
Reference:
http://www.cs.princeton.edu/~wayne/kleinberg-tardos/pdf/04GreedyAlgorithmsII.pdf
http://www.geeksforgeeks.org/greedy-algorithms-set-9-boruvkas-algorithm/