gtsam/gtsam_unstable/base/DSFMap.h

123 lines
2.9 KiB
C
Raw Normal View History

/* ----------------------------------------------------------------------------
* GTSAM Copyright 2010, Georgia Tech Research Corporation,
* Atlanta, Georgia 30332-0415
* All Rights Reserved
* Authors: Frank Dellaert, et al. (see THANKS for the full author list)
* See LICENSE for the license information
* -------------------------------------------------------------------------- */
/**
* @file DSFMap.h
* @date Oct 26, 2013
* @author Frank Dellaert
* @brief Allow for arbitrary type in DSF
*/
#pragma once
#include <map>
2013-10-27 06:22:31 +08:00
#include <set>
namespace gtsam {
/**
* Disjoint set forest using an STL map data structure underneath
2013-10-27 10:50:47 +08:00
* Uses rank compression and union by rank, iterator version
* @addtogroup base
*/
template<class KEY>
class DSFMap {
2013-10-27 10:18:42 +08:00
protected:
/// We store the forest in an STL map, but parents are done with pointers
struct Entry {
typedef std::map<KEY, Entry> Map;
typename Map::iterator parent_;
Entry() {}
2013-10-27 10:18:42 +08:00
size_t rank_;
};
2013-10-27 10:50:47 +08:00
typedef typename Entry::Map::iterator iterator;
mutable typename Entry::Map entries_;
2013-10-27 10:18:42 +08:00
2013-10-27 10:50:47 +08:00
/// Given key, find iterator to initial entry
iterator find__(const KEY& key) const {
static const Entry empty;
iterator it = entries_.find(key);
2013-10-27 10:18:42 +08:00
// if key does not exist, create and return itself
if (it == entries_.end()) {
it = entries_.insert(std::make_pair(key, empty)).first;
it->second.parent_ = it;
it->second.rank_ = 0;
2013-10-27 10:18:42 +08:00
}
2013-10-27 10:50:47 +08:00
return it;
2013-10-27 10:18:42 +08:00
}
2013-10-27 10:50:47 +08:00
/// Given iterator to initial entry, find the root Entry
iterator find_(const iterator& it) const {
2013-10-27 10:18:42 +08:00
// follow parent pointers until we reach set representative
iterator& parent = it->second.parent_;
if (parent != it)
parent = find_(parent); // not yet, recurse!
2013-10-27 10:18:42 +08:00
return parent;
}
2013-10-27 10:50:47 +08:00
/// Given key, find the root Entry
inline iterator find_(const KEY& key) const {
iterator initial = find__(key);
return find_(initial);
2013-10-27 10:50:47 +08:00
}
2013-10-27 10:18:42 +08:00
public:
2013-10-27 10:50:47 +08:00
typedef std::set<KEY> Set;
2013-10-27 10:18:42 +08:00
/// constructor
2013-10-27 10:50:47 +08:00
DSFMap() {
2013-10-27 10:18:42 +08:00
}
2013-10-27 10:50:47 +08:00
/// Given key, find the representative key for the set in which it lives
inline KEY find(const KEY& key) const {
iterator root = find_(key);
return root->first;
2013-10-27 10:18:42 +08:00
}
/// Merge two sets
void merge(const KEY& x, const KEY& y) {
// straight from http://en.wikipedia.org/wiki/Disjoint-set_data_structure
iterator xRoot = find_(x);
iterator yRoot = find_(y);
2013-10-27 10:18:42 +08:00
if (xRoot == yRoot)
return;
// Merge sets
if (xRoot->second.rank_ < yRoot->second.rank_)
xRoot->second.parent_ = yRoot;
else if (xRoot->second.rank_ > yRoot->second.rank_)
yRoot->second.parent_ = xRoot;
2013-10-27 10:18:42 +08:00
else {
yRoot->second.parent_ = xRoot;
xRoot->second.rank_ = xRoot->second.rank_ + 1;
2013-10-27 10:18:42 +08:00
}
}
2013-10-27 10:50:47 +08:00
/// return all sets, i.e. a partition of all elements
std::map<KEY, Set> sets() const {
std::map<KEY, Set> sets;
iterator it = entries_.begin();
for (; it != entries_.end(); it++) {
iterator root = find_(it);
sets[root->first].insert(it->first);
2013-10-27 10:18:42 +08:00
}
2013-10-27 10:50:47 +08:00
return sets;
2013-10-27 10:18:42 +08:00
}
2013-10-27 06:22:31 +08:00
};
}