Program Listing for File kruskal-max-span-tree.h¶
↰ Return to documentation for file (common/maplab-common/include/maplab-common/kruskal-max-span-tree.h
)
#ifndef MAPLAB_COMMON_KRUSKAL_MAX_SPAN_TREE_H_
#define MAPLAB_COMMON_KRUSKAL_MAX_SPAN_TREE_H_
#include <algorithm>
#include <stack>
#include <vector>
#include <glog/logging.h>
namespace common {
// Find root with path compression, returns root of v.
__inline__ int FindRoot(int node, std::vector<int>* edge_list) {
CHECK_NOTNULL(edge_list);
std::stack<int> stck;
stck.push(node);
while ((*edge_list)[node] != node) { // Find root.
node = (*edge_list)[node];
stck.push(node);
}
while (!stck.empty()) { // Compress children.
(*edge_list)[stck.top()] = node;
stck.pop();
}
return node;
}
// Union of tree-partitions by size.
__inline__ void UnionClusters(
int node_a, int node_b, std::vector<int>* parent, std::vector<int>* rank) {
CHECK_NOTNULL(parent);
CHECK_NOTNULL(rank);
if ((*rank)[node_a] < (*rank)[node_b]) {
(*parent)[node_a] = node_b;
} else if ((*rank)[node_a] > (*rank)[node_b]) {
(*parent)[node_b] = node_a;
} else {
(*parent)[node_b] = node_a;
++((*rank)[node_a]);
}
}
template <template <typename, typename> class EdgeContainer,
template <typename> class EdgeAllocator, typename Edge>
__inline__ bool KruskalMaxSpanTree(
int num_vertices, EdgeContainer<Edge, EdgeAllocator<Edge> >* edges) {
CHECK_NOTNULL(edges);
std::vector<int> parents;
parents.reserve(num_vertices);
for (int i = 0; i < num_vertices; ++i) {
parents.push_back(i);
}
std::vector<int> vi_rank;
vi_rank.reserve(num_vertices);
vi_rank.insert(vi_rank.begin(), num_vertices, 1);
edges->sort([](const Edge& lhs, const Edge& rhs) {
return std::get<2>(lhs) > std::get<2>(rhs);
});
int in_tree_edges = 0;
typename EdgeContainer<Edge, EdgeAllocator<Edge> >::iterator edge_it =
edges->begin();
while (in_tree_edges < num_vertices - 1 && edge_it != edges->end()) {
Edge& edge = *edge_it;
if (FindRoot(std::get<0>(edge), &parents) !=
FindRoot(std::get<1>(edge), &parents)) {
UnionClusters(
parents[std::get<0>(edge)], parents[std::get<1>(edge)], &parents,
&vi_rank);
++in_tree_edges;
++edge_it;
} else {
edge_it = edges->erase(edge_it);
}
}
edges->erase(edge_it, edges->end());
if (static_cast<int>(edges->size()) != num_vertices - 1) {
return false;
} else {
LOG(INFO) << "Done. Got " << edges->size() << " edges in MST.";
return true;
}
}
} // namespace common
#endif // MAPLAB_COMMON_KRUSKAL_MAX_SPAN_TREE_H_