BTree.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  1. /* ----------------------------------------------------------------------------
  2. * GTSAM Copyright 2010, Georgia Tech Research Corporation,
  3. * Atlanta, Georgia 30332-0415
  4. * All Rights Reserved
  5. * Authors: Frank Dellaert, et al. (see THANKS for the full author list)
  6. * See LICENSE for the license information
  7. * -------------------------------------------------------------------------- */
  8. /**
  9. * @file BTree.h
  10. * @brief purely functional binary tree
  11. * @author Chris Beall
  12. * @author Frank Dellaert
  13. * @date Feb 3, 2010
  14. */
  15. #include <stack>
  16. #include <sstream>
  17. #include <boost/shared_ptr.hpp>
  18. #include <functional>
  19. namespace gtsam {
  20. /**
  21. * @brief Binary tree
  22. * @addtogroup base
  23. */
  24. template<class KEY, class VALUE>
  25. class BTree {
  26. public:
  27. typedef std::pair<KEY, VALUE> value_type;
  28. private:
  29. /**
  30. * Node in a tree
  31. */
  32. struct Node {
  33. const size_t height_;
  34. const value_type keyValue_;
  35. const BTree left, right;
  36. /** default constructor */
  37. Node() {
  38. }
  39. /**
  40. * Create leaf node with height 1
  41. * @param keyValue (key,value) pair
  42. */
  43. Node(const value_type& keyValue) :
  44. height_(1), keyValue_(keyValue) {
  45. }
  46. /**
  47. * Create a node from two subtrees and a key value pair
  48. */
  49. Node(const BTree& l, const value_type& keyValue, const BTree& r) :
  50. height_(l.height() >= r.height() ? l.height() + 1 : r.height() + 1),
  51. keyValue_(keyValue), left(l), right(r) {
  52. }
  53. inline const KEY& key() const { return keyValue_.first;}
  54. inline const VALUE& value() const { return keyValue_.second;}
  55. }; // Node
  56. // We store a shared pointer to the root of the functional tree
  57. // composed of Node classes. If root_==nullptr, the tree is empty.
  58. typedef boost::shared_ptr<const Node> sharedNode;
  59. sharedNode root_;
  60. inline const value_type& keyValue() const { return root_->keyValue_;}
  61. inline const KEY& key() const { return root_->key(); }
  62. inline const VALUE& value() const { return root_->value(); }
  63. inline const BTree& left() const { return root_->left; }
  64. inline const BTree& right() const { return root_->right; }
  65. /** create a new balanced tree out of two trees and a key-value pair */
  66. static BTree balance(const BTree& l, const value_type& xd, const BTree& r) {
  67. size_t hl = l.height(), hr = r.height();
  68. if (hl > hr + 2) {
  69. const BTree& ll = l.left(), lr = l.right();
  70. if (ll.height() >= lr.height())
  71. return BTree(ll, l.keyValue(), BTree(lr, xd, r));
  72. else {
  73. BTree _left(ll, l.keyValue(), lr.left());
  74. BTree _right(lr.right(), xd, r);
  75. return BTree(_left, lr.keyValue(), _right);
  76. }
  77. } else if (hr > hl + 2) {
  78. const BTree& rl = r.left(), rr = r.right();
  79. if (rr.height() >= rl.height())
  80. return BTree(BTree(l, xd, rl), r.keyValue(), rr);
  81. else {
  82. BTree _left(l, xd, rl.left());
  83. BTree _right(rl.right(), r.keyValue(), rr);
  84. return BTree(_left, rl.keyValue(), _right);
  85. }
  86. } else
  87. return BTree(l, xd, r);
  88. }
  89. public:
  90. /** default constructor creates an empty tree */
  91. BTree() {
  92. }
  93. /** copy constructor */
  94. BTree(const BTree& other) :
  95. root_(other.root_) {
  96. }
  97. /** create leaf from key-value pair */
  98. BTree(const value_type& keyValue) :
  99. root_(new Node(keyValue)) {
  100. }
  101. /** create from key-value pair and left, right subtrees */
  102. BTree(const BTree& l, const value_type& keyValue, const BTree& r) :
  103. root_(new Node(l, keyValue, r)) {
  104. }
  105. /** assignment operator */
  106. BTree & operator= (const BTree & other) {
  107. root_ = other.root_;
  108. return *this;
  109. }
  110. /** Check whether tree is empty */
  111. bool empty() const {
  112. return !root_;
  113. }
  114. /** add a key-value pair */
  115. BTree add(const value_type& xd) const {
  116. if (empty()) return BTree(xd);
  117. const KEY& x = xd.first;
  118. if (x == key())
  119. return BTree(left(), xd, right());
  120. else if (x < key())
  121. return balance(left().add(xd), keyValue(), right());
  122. else
  123. return balance(left(), keyValue(), right().add(xd));
  124. }
  125. /** add a key-value pair */
  126. BTree add(const KEY& x, const VALUE& d) const {
  127. return add(std::make_pair(x, d));
  128. }
  129. /** member predicate */
  130. bool mem(const KEY& x) const {
  131. if (!root_) return false;
  132. if (x == key()) return true;
  133. if (x < key())
  134. return left().mem(x);
  135. else
  136. return right().mem(x);
  137. }
  138. /** Check whether trees are *exactly* the same (occupy same memory) */
  139. inline bool same(const BTree& other) const {
  140. return (other.root_ == root_);
  141. }
  142. /**
  143. * Check whether trees are structurally the same,
  144. * i.e., contain the same values in same tree-structure.
  145. */
  146. bool operator==(const BTree& other) const {
  147. if (other.root_ == root_) return true; // if same, we're done
  148. if (empty() && !other.empty()) return false;
  149. if (!empty() && other.empty()) return false;
  150. // both non-empty, recurse: check this key-value pair and subtrees...
  151. return (keyValue() == other.keyValue()) && (left() == other.left())
  152. && (right() == other.right());
  153. }
  154. inline bool operator!=(const BTree& other) const {
  155. return !operator==(other);
  156. }
  157. /** minimum key binding */
  158. const value_type& min() const {
  159. if (!root_) throw std::invalid_argument("BTree::min: empty tree");
  160. if (left().empty()) return keyValue();
  161. return left().min();
  162. }
  163. /** remove minimum key binding */
  164. BTree remove_min() const {
  165. if (!root_) throw std::invalid_argument("BTree::remove_min: empty tree");
  166. if (left().empty()) return right();
  167. return balance(left().remove_min(), keyValue(), right());
  168. }
  169. /** merge two trees */
  170. static BTree merge(const BTree& t1, const BTree& t2) {
  171. if (t1.empty()) return t2;
  172. if (t2.empty()) return t1;
  173. const value_type& xd = t2.min();
  174. return balance(t1, xd, t2.remove_min());
  175. }
  176. /** remove a key-value pair */
  177. BTree remove(const KEY& x) const {
  178. if (!root_) return BTree();
  179. if (x == key())
  180. return merge(left(), right());
  181. else if (x < key())
  182. return balance(left().remove(x), keyValue(), right());
  183. else
  184. return balance(left(), keyValue(), right().remove(x));
  185. }
  186. /** Return height of the tree, 0 if empty */
  187. size_t height() const {
  188. return (root_ != nullptr) ? root_->height_ : 0;
  189. }
  190. /** return size of the tree */
  191. size_t size() const {
  192. if (!root_) return 0;
  193. return left().size() + 1 + right().size();
  194. }
  195. /**
  196. * find a value given a key, throws exception when not found
  197. * Optimized non-recursive version as [find] is crucial for speed
  198. */
  199. const VALUE& find(const KEY& k) const {
  200. const Node* node = root_.get();
  201. while (node) {
  202. const KEY& key = node->key();
  203. if (k < key) node = node->left.root_.get();
  204. else if (key < k) node = node->right.root_.get();
  205. else return node->value();
  206. }
  207. throw std::invalid_argument("BTree::find: key not found");
  208. }
  209. /** print in-order */
  210. void print(const std::string& s = "") const {
  211. if (empty()) return;
  212. KEY k = key();
  213. std::stringstream ss;
  214. ss << height();
  215. k.print(s + ss.str() + " ");
  216. left().print(s + "L ");
  217. right().print(s + "R ");
  218. }
  219. /** iterate over tree */
  220. void iter(std::function<void(const KEY&, const VALUE&)> f) const {
  221. if (!root_) return;
  222. left().iter(f);
  223. f(key(), value());
  224. right().iter(f);
  225. }
  226. /** map key-values in tree over function f that computes a new value */
  227. template<class TO>
  228. BTree<KEY, TO> map(std::function<TO(const KEY&, const VALUE&)> f) const {
  229. if (empty()) return BTree<KEY, TO> ();
  230. std::pair<KEY, TO> xd(key(), f(key(), value()));
  231. return BTree<KEY, TO> (left().map(f), xd, right().map(f));
  232. }
  233. /**
  234. * t.fold(f,a) computes [(f kN dN ... (f k1 d1 a)...)],
  235. * where [k1 ... kN] are the keys of all bindings in [m],
  236. * and [d1 ... dN] are the associated data.
  237. * The associated values are passed to [f] in reverse sort order
  238. */
  239. template<class ACC>
  240. ACC fold(std::function<ACC(const KEY&, const VALUE&, const ACC&)> f,
  241. const ACC& a) const {
  242. if (!root_) return a;
  243. ACC ar = right().fold(f, a); // fold over right subtree
  244. ACC am = f(key(), value(), ar); // apply f with current value
  245. return left().fold(f, am); // fold over left subtree
  246. }
  247. /**
  248. * @brief Const iterator
  249. * Not trivial: iterator keeps a stack to indicate current path from root_
  250. */
  251. class const_iterator {
  252. private:
  253. typedef const_iterator Self;
  254. typedef std::pair<sharedNode, bool> flagged;
  255. /** path to the iterator, annotated with flag */
  256. std::stack<flagged> path_;
  257. const sharedNode& current() const {
  258. return path_.top().first;
  259. }
  260. bool done() const {
  261. return path_.top().second;
  262. }
  263. // The idea is we already iterated through the left-subtree and current key-value.
  264. // We now try pushing left subtree of right onto the stack. If there is no right
  265. // sub-tree, we pop this node of the stack and the parent becomes the iterator.
  266. // We avoid going down a right-subtree that was already visited by checking the flag.
  267. void increment() {
  268. if (path_.empty()) return;
  269. sharedNode t = current()->right.root_;
  270. if (!t || done()) {
  271. // no right subtree, iterator becomes first parent with a non-visited right subtree
  272. path_.pop();
  273. while (!path_.empty() && done())
  274. path_.pop();
  275. } else {
  276. path_.top().second = true; // flag we visited right
  277. // push right root and its left-most path onto the stack
  278. while (t) {
  279. path_.push(std::make_pair(t, false));
  280. t = t->left.root_;
  281. }
  282. }
  283. }
  284. public:
  285. // traits for playing nice with STL
  286. typedef ptrdiff_t difference_type;
  287. typedef std::forward_iterator_tag iterator_category;
  288. typedef std::pair<KEY, VALUE> value_type;
  289. typedef const value_type* pointer;
  290. typedef const value_type& reference;
  291. /** initialize end */
  292. const_iterator() {
  293. }
  294. /** initialize from root */
  295. const_iterator(const sharedNode& root) {
  296. sharedNode t = root;
  297. while (t) {
  298. path_.push(std::make_pair(t, false));
  299. t = t->left.root_;
  300. }
  301. }
  302. /** equality */
  303. bool operator==(const Self& __x) const {
  304. return path_ == __x.path_;
  305. }
  306. /** inequality */
  307. bool operator!=(const Self& __x) const {
  308. return path_ != __x.path_;
  309. }
  310. /** dereference */
  311. reference operator*() const {
  312. if (path_.empty()) throw std::invalid_argument(
  313. "operator*: tried to dereference end");
  314. return current()->keyValue_;
  315. }
  316. /** dereference */
  317. pointer operator->() const {
  318. if (path_.empty()) throw std::invalid_argument(
  319. "operator->: tried to dereference end");
  320. return &(current()->keyValue_);
  321. }
  322. /** pre-increment */
  323. Self& operator++() {
  324. increment();
  325. return *this;
  326. }
  327. /** post-increment */
  328. Self operator++(int) {
  329. Self __tmp = *this;
  330. increment();
  331. return __tmp;
  332. }
  333. }; // const_iterator
  334. // to make BTree work with range-based for
  335. // We do *not* want a non-const iterator
  336. typedef const_iterator iterator;
  337. /** return iterator */
  338. const_iterator begin() const {
  339. return const_iterator(root_);
  340. }
  341. /** return iterator */
  342. const_iterator end() const {
  343. return const_iterator();
  344. }
  345. }; // BTree
  346. } // namespace gtsam