Faster variant of DSFMap, if not as elegant.

release/4.3a0
Frank Dellaert 2013-10-27 03:45:12 +00:00
parent d1a62b0cc1
commit b88e15e694
2 changed files with 33 additions and 37 deletions

View File

@ -35,45 +35,41 @@ protected:
/// We store the forest in an STL map, but parents are done with pointers /// We store the forest in an STL map, but parents are done with pointers
struct Entry { struct Entry {
KEY key_; typedef std::map<KEY, Entry> Map;
typename Map::iterator parent_;
Entry() {}
size_t rank_; size_t rank_;
Entry* parent_;
Entry(KEY key) :
key_(key), rank_(0), parent_(0) {
}
void makeRoot() {
parent_ = this;
}
}; };
typedef std::map<KEY, Entry> Map; typedef typename Entry::Map::iterator iterator;
mutable Map entries_; mutable typename Entry::Map entries_;
/// Given key, find iterator to initial entry /// Given key, find iterator to initial entry
typename Map::iterator find__(const KEY& key) const { iterator find__(const KEY& key) const {
typename Map::iterator it = entries_.find(key); static const Entry empty;
iterator it = entries_.find(key);
// if key does not exist, create and return itself // if key does not exist, create and return itself
if (it == entries_.end()) { if (it == entries_.end()) {
it = entries_.insert(it, std::make_pair(key, Entry(key))); it = entries_.insert(std::make_pair(key, empty)).first;
it->second.makeRoot(); it->second.parent_ = it;
it->second.rank_ = 0;
} }
return it; return it;
} }
/// Given iterator to initial entry, find the root Entry /// Given iterator to initial entry, find the root Entry
Entry* find_(const typename Map::iterator& it) const { iterator find_(const iterator& it) const {
// follow parent pointers until we reach set representative // follow parent pointers until we reach set representative
Entry* parent = it->second.parent_; iterator& parent = it->second.parent_;
while (parent->parent_ != parent) if (parent != it)
parent = parent->parent_; // not yet, recurse! parent = find_(parent); // not yet, recurse!
it->second.parent_ = parent; // path compression
return parent; return parent;
} }
/// Given key, find the root Entry /// Given key, find the root Entry
Entry* find_(const KEY& key) const { inline iterator find_(const KEY& key) const {
typename Map::iterator it = find__(key); iterator initial = find__(key);
return find_(it); return find_(initial);
} }
public: public:
@ -85,38 +81,38 @@ public:
} }
/// Given key, find the representative key for the set in which it lives /// Given key, find the representative key for the set in which it lives
KEY find(const KEY& key) const { inline KEY find(const KEY& key) const {
Entry* root = find_(key); iterator root = find_(key);
return root->key_; return root->first;
} }
/// Merge two sets /// Merge two sets
void merge(const KEY& x, const KEY& y) { void merge(const KEY& x, const KEY& y) {
// straight from http://en.wikipedia.org/wiki/Disjoint-set_data_structure // straight from http://en.wikipedia.org/wiki/Disjoint-set_data_structure
Entry* xRoot = find_(x); iterator xRoot = find_(x);
Entry* yRoot = find_(y); iterator yRoot = find_(y);
if (xRoot == yRoot) if (xRoot == yRoot)
return; return;
// Merge sets // Merge sets
if (xRoot->rank_ < yRoot->rank_) if (xRoot->second.rank_ < yRoot->second.rank_)
xRoot->parent_ = yRoot; xRoot->second.parent_ = yRoot;
else if (xRoot->rank_ > yRoot->rank_) else if (xRoot->second.rank_ > yRoot->second.rank_)
yRoot->parent_ = xRoot; yRoot->second.parent_ = xRoot;
else { else {
yRoot->parent_ = xRoot; yRoot->second.parent_ = xRoot;
xRoot->rank_ = xRoot->rank_ + 1; xRoot->second.rank_ = xRoot->second.rank_ + 1;
} }
} }
/// return all sets, i.e. a partition of all elements /// return all sets, i.e. a partition of all elements
std::map<KEY, Set> sets() const { std::map<KEY, Set> sets() const {
std::map<KEY, Set> sets; std::map<KEY, Set> sets;
typename Map::iterator it = entries_.begin(); iterator it = entries_.begin();
for(;it!=entries_.end();it++) { for (; it != entries_.end(); it++) {
Entry* root = find_(it); iterator root = find_(it);
sets[root->key_].insert(it->first); sets[root->first].insert(it->first);
} }
return sets; return sets;
} }

Binary file not shown.