| 
									
										
										
										
											2010-02-05 05:02:05 +08:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  *  Created on: Feb 3, 2010 | 
					
						
							|  |  |  |  *      Author: cbeall3 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <boost/shared_ptr.hpp>
 | 
					
						
							|  |  |  | #include <CppUnitLite/TestHarness.h>
 | 
					
						
							|  |  |  | #include "Key.h"
 | 
					
						
							| 
									
										
										
										
											2010-02-06 23:53:31 +08:00
										 |  |  | #include <iostream>
 | 
					
						
							|  |  |  | #include <sstream>
 | 
					
						
							| 
									
										
										
										
											2010-02-05 05:02:05 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | //    type 'a t =
 | 
					
						
							|  |  |  | //        Empty
 | 
					
						
							|  |  |  | //      | Node of 'a t * key * 'a * 'a t * int
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace gtsam{ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template <class Key, class Value> | 
					
						
							|  |  |  | struct Node { | 
					
						
							|  |  |  | 	typedef boost::shared_ptr<Node> Tree; | 
					
						
							|  |  |  | 	Tree left_, right_; | 
					
						
							|  |  |  | 	Key key_; | 
					
						
							|  |  |  | 	Value value_; | 
					
						
							|  |  |  | 	size_t height_; | 
					
						
							|  |  |  | 	/**
 | 
					
						
							|  |  |  | 	 * leaf node with height 1 | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	Node(const Key& key, const Value& value) | 
					
						
							|  |  |  | 	:key_(key),value_(value),height_(1) {} | 
					
						
							|  |  |  | 	Node(const Tree& l, const Key& key, const Value& value, const Tree& r, size_t height) | 
					
						
							|  |  |  | 	:left_(l),key_(key),value_(value),right_(r),height_(height) {} | 
					
						
							|  |  |  | 	Node() {} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template <class Key, class Value> | 
					
						
							|  |  |  | size_t height(const typename boost::shared_ptr<Node<Key,Value> >& t) { | 
					
						
							|  |  |  | 	if (t) return t->height_; else return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template <class Key, class Value> | 
					
						
							|  |  |  | typename Node<Key,Value>::Tree create(const typename Node<Key,Value>::Tree& l, const Key& key, | 
					
						
							|  |  |  | 		const Value& value, const typename Node<Key,Value>::Tree& r) { | 
					
						
							|  |  |  | 	size_t hl = height(l), hr = height(r); | 
					
						
							|  |  |  | 	size_t h = hl >= hr ? hl + 1 : hr + 1; | 
					
						
							|  |  |  | 	return typename Node<Key,Value>::Tree(new Node<Key, Value>(l,key,value,r, h)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template <class Key, class Value> | 
					
						
							|  |  |  | typename Node<Key,Value>::Tree bal(const typename Node<Key,Value>::Tree& l, const Key& key, | 
					
						
							|  |  |  | 		const Value& value, const typename Node<Key,Value>::Tree& r) { | 
					
						
							|  |  |  | 	size_t hl = height(l), hr = height(r); | 
					
						
							|  |  |  | 	if(hl > hr+2) { | 
					
						
							|  |  |  | 		if(hl == 0) throw("Left tree is empty"); | 
					
						
							| 
									
										
										
										
											2010-02-07 01:45:40 +08:00
										 |  |  | 		else if(height(l->left_) >= height(l->right_)) { | 
					
						
							| 
									
										
										
										
											2010-02-05 05:02:05 +08:00
										 |  |  | 		  //  create ll lv ld (create lr x d r)
 | 
					
						
							|  |  |  | 			return create(l->left_,l->key_,l->value_, create(l->right_, key, value, r)); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else{ | 
					
						
							| 
									
										
										
										
											2010-02-07 01:45:40 +08:00
										 |  |  | 			if(height(l->right_) == 0) throw("Left->Right is empty"); | 
					
						
							| 
									
										
										
										
											2010-02-05 05:02:05 +08:00
										 |  |  | 			else { | 
					
						
							|  |  |  | 				 // create (create ll lv ld lrl) lrv lrd (create lrr x d r)
 | 
					
						
							|  |  |  | 				return create( | 
					
						
							|  |  |  | 						create(l->left_,l->key_,l->value_,l->right_->left_), | 
					
						
							|  |  |  | 						l->right_->key_, | 
					
						
							|  |  |  | 						l->right_->value_, | 
					
						
							|  |  |  | 						create(l->right_->right_,key,value,r)); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if (hr > hl + 2) { | 
					
						
							|  |  |  | 		if(hr == 0) throw("Right tree is empty"); | 
					
						
							| 
									
										
										
										
											2010-02-07 01:45:40 +08:00
										 |  |  | 		else if(height(r->right_) >= height(r->left_)) { | 
					
						
							| 
									
										
										
										
											2010-02-05 05:02:05 +08:00
										 |  |  | 			//  create (create l x d rl) rv rd rr
 | 
					
						
							|  |  |  | 			return create(create(l,key,value,r->left_),r->key_,r->value_,r); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else{ | 
					
						
							| 
									
										
										
										
											2010-02-07 01:45:40 +08:00
										 |  |  | 			if(height(r->left_) == 0) throw("Right->Left is empty"); | 
					
						
							| 
									
										
										
										
											2010-02-05 05:02:05 +08:00
										 |  |  | 		  else { | 
					
						
							|  |  |  | 			  //  create (create l x d rll) rlv rld (create rlr rv rd rr)
 | 
					
						
							|  |  |  | 			  return create( | 
					
						
							|  |  |  | 			  		create(l,key,value,r->left_->left_), | 
					
						
							|  |  |  | 			  		r->left_->key_, | 
					
						
							|  |  |  | 			  		r->left_->value_, | 
					
						
							|  |  |  | 			  		create(r->left_->right_,r->key_,r->value_,r->right_)); | 
					
						
							|  |  |  | 		  } | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  |     return create(l,key,value,r); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template <class Key, class Value> | 
					
						
							|  |  |  | typename Node<Key, Value>::Tree add(const Key& key, const Value& value, const typename Node<Key,Value>::Tree& tree) { | 
					
						
							|  |  |  | 	if(tree == NULL) { | 
					
						
							|  |  |  | 		return typename Node<Key,Value>::Tree(new Node<Key,Value>(key, value)); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if(key == tree->key_) { | 
					
						
							| 
									
										
										
										
											2010-02-07 01:45:40 +08:00
										 |  |  | 		return typename Node<Key,Value>::Tree(new Node<Key, Value>(tree->left_, key, value, tree->right_, height(tree))); | 
					
						
							| 
									
										
										
										
											2010-02-05 05:02:05 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else if( key < tree->key_) { | 
					
						
							|  |  |  | 		return bal(add(key, value, tree->left_), tree->key_, tree->value_, tree->right_); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		return bal(tree->left_, tree->key_, tree->value_, add(key, value, tree->right_)); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template <class Key, class Value> | 
					
						
							| 
									
										
										
										
											2010-02-06 23:53:31 +08:00
										 |  |  | boost::optional<Value> find(const typename boost::shared_ptr<Node<Key,Value> >& tree, const Key& key){ | 
					
						
							| 
									
										
										
										
											2010-02-05 05:02:05 +08:00
										 |  |  |   if(tree->key_ == key) | 
					
						
							|  |  |  |   	return tree->value_; | 
					
						
							| 
									
										
										
										
											2010-02-06 23:53:31 +08:00
										 |  |  |   if(key < tree->key_ && tree->left_ != NULL) | 
					
						
							| 
									
										
										
										
											2010-02-05 05:02:05 +08:00
										 |  |  |   	return find(tree->left_, key); | 
					
						
							| 
									
										
										
										
											2010-02-06 23:53:31 +08:00
										 |  |  |   else if(tree->right_ != NULL) | 
					
						
							| 
									
										
										
										
											2010-02-05 05:02:05 +08:00
										 |  |  |   	return find(tree->right_,key); | 
					
						
							| 
									
										
										
										
											2010-02-06 23:53:31 +08:00
										 |  |  |   return boost::none; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template <class Key, class Value> | 
					
						
							|  |  |  | typename Node<Key, Value>::Tree begin(const typename Node<Key,Value>::Tree& tree) { | 
					
						
							|  |  |  | 	if(tree->left_ !=NULL){ | 
					
						
							|  |  |  | 		return begin(tree->left_); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		return tree; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template <class Key, class Value> | 
					
						
							|  |  |  | typename Node<Key, Value>::Tree end(const typename Node<Key,Value>::Tree& tree) { | 
					
						
							|  |  |  | 	if(tree->right_ !=NULL){ | 
					
						
							|  |  |  | 		return begin(tree->right_); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		return tree; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template <class Key, class Value> | 
					
						
							|  |  |  | void walk(const typename boost::shared_ptr<Node<Key,Value> >& tree, std::string s) { | 
					
						
							|  |  |  | 	if(tree->left_ !=NULL) { | 
					
						
							|  |  |  | 		walk(tree->left_, s+"->l"); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	Key k = tree->key_; | 
					
						
							|  |  |  | 	std::stringstream ss; | 
					
						
							| 
									
										
										
										
											2010-02-07 01:45:40 +08:00
										 |  |  | 	ss << height(tree); | 
					
						
							| 
									
										
										
										
											2010-02-06 23:53:31 +08:00
										 |  |  | 	k.print(ss.str() +" "+ s); | 
					
						
							|  |  |  | 	if(tree->right_ !=NULL) { | 
					
						
							|  |  |  | 		walk(tree->right_, s+"->r"); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2010-02-05 05:02:05 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } |