124 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			C++
		
	
	
			
		
		
	
	
			124 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			C++
		
	
	
/* ----------------------------------------------------------------------------
 | 
						|
 | 
						|
 * 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>
 | 
						|
#include <set>
 | 
						|
#include <cstdlib>        // Provides size_t
 | 
						|
 | 
						|
namespace gtsam {
 | 
						|
 | 
						|
/**
 | 
						|
 * Disjoint set forest using an STL map data structure underneath
 | 
						|
 * Uses rank compression and union by rank, iterator version
 | 
						|
 * @addtogroup base
 | 
						|
 */
 | 
						|
template<class KEY>
 | 
						|
class DSFMap {
 | 
						|
 | 
						|
protected:
 | 
						|
 | 
						|
  /// We store the forest in an STL map, but parents are done with pointers
 | 
						|
  struct Entry {
 | 
						|
    typename std::map<KEY, Entry>::iterator parent_;
 | 
						|
    size_t rank_;
 | 
						|
    Entry() {}
 | 
						|
  };
 | 
						|
 | 
						|
    typedef typename std::map<KEY, Entry> Map;
 | 
						|
  typedef typename Map::iterator iterator;
 | 
						|
  mutable Map entries_;
 | 
						|
 | 
						|
  /// Given key, find iterator to initial entry
 | 
						|
  iterator find__(const KEY& key) const {
 | 
						|
    static const Entry empty;
 | 
						|
    iterator it = entries_.find(key);
 | 
						|
    // 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;
 | 
						|
    }
 | 
						|
    return it;
 | 
						|
  }
 | 
						|
 | 
						|
  /// Given iterator to initial entry, find the root Entry
 | 
						|
  iterator find_(const iterator& it) const {
 | 
						|
    // follow parent pointers until we reach set representative
 | 
						|
    iterator& parent = it->second.parent_;
 | 
						|
    if (parent != it)
 | 
						|
      parent = find_(parent); // not yet, recurse!
 | 
						|
    return parent;
 | 
						|
  }
 | 
						|
 | 
						|
  /// Given key, find the root Entry
 | 
						|
  inline iterator find_(const KEY& key) const {
 | 
						|
    iterator initial = find__(key);
 | 
						|
    return find_(initial);
 | 
						|
  }
 | 
						|
 | 
						|
public:
 | 
						|
 | 
						|
  typedef std::set<KEY> Set;
 | 
						|
 | 
						|
  /// constructor
 | 
						|
  DSFMap() {
 | 
						|
  }
 | 
						|
 | 
						|
  /// 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;
 | 
						|
  }
 | 
						|
 | 
						|
  /// 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);
 | 
						|
    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;
 | 
						|
    else {
 | 
						|
      yRoot->second.parent_ = xRoot;
 | 
						|
      xRoot->second.rank_ = xRoot->second.rank_ + 1;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  /// 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);
 | 
						|
    }
 | 
						|
    return sets;
 | 
						|
  }
 | 
						|
 | 
						|
};
 | 
						|
 | 
						|
}
 |