00001 // Copyright 2007, Massachusetts Institute of Technology. 00002 // The use of this code is permitted for research only. There is 00003 // absolutely no warranty for this software. 00004 // 00005 // Author: John Lee (jjl@mit.edu) 00006 // 00007 00008 #ifndef TREE_SPARSE_TREE_H 00009 #define TREE_SPARSE_TREE_H 00010 00011 #include <list> 00012 #include <stack> 00013 #include "tree/sparse-tree-node.h" 00014 00015 using namespace std; 00016 00017 namespace libpmk { 00018 00021 00080 template <class T> 00081 class SparseTree { 00082 public: 00083 SparseTree(); 00084 ~SparseTree(); 00085 00087 SparseTree(const SparseTree<T>& other); 00088 SparseTree(const SparseTree<T>& one, const SparseTree<T>& two); 00089 00090 class Iterator; 00091 class PreorderIterator; 00092 class PostorderIterator; 00093 class BreadthFirstIterator; 00094 00096 T* root() { return root_node_; } 00097 00099 T* const root() const { return root_node_; } 00100 00102 int size() const { return num_nodes_; } 00103 00105 00108 T* node(const LargeIndex& index); 00109 00111 00116 T* node(const LargeIndex& index, SparseTreeNode* finger); 00117 00118 00119 00121 00138 T* add_node(const T& new_node); 00139 00141 00147 T* add_node(const T& new_node, SparseTreeNode* parent); 00148 00150 00162 void ReadFromStream(istream& input_stream); 00163 00165 00169 void WriteToStream(ostream& output_stream) const; 00170 00171 00173 00177 void remove_node(SparseTreeNode* node); 00178 00180 PreorderIterator BeginPreorder() const; 00181 00183 static const PreorderIterator& EndPreorder(); 00184 00186 PostorderIterator BeginPostorder() const; 00187 00189 static const PostorderIterator& EndPostorder(); 00190 00192 BreadthFirstIterator BeginBreadthFirst() const; 00193 00195 static const BreadthFirstIterator& EndBreadthFirst(); 00196 00198 class Iterator { 00199 public: 00201 Iterator(SparseTreeNode* node) : node_(node) {} 00202 virtual ~Iterator() {} 00203 00205 Iterator& operator=(const Iterator& other) { 00206 node_ = other.node_; 00207 return *this; 00208 } 00209 00211 bool operator==(const Iterator& other) { 00212 return node_ == other.node_; 00213 } 00214 00216 bool operator!=(const Iterator& other) { 00217 return node_ != other.node_; 00218 } 00219 00221 T* operator->() { 00222 return static_cast<T*>(node_); 00223 } 00224 00226 T* get() { 00227 return static_cast<T*>(node_); 00228 } 00229 virtual Iterator& operator++() = 0; 00230 00231 protected: 00232 SparseTreeNode* node_; 00233 }; 00234 00235 00236 // Internally, we let <node_> be the current position. <todo_> 00237 // contains all remaining nodes, but the nodes in <todo_> may 00238 // have yet to be expanded. 00240 class PreorderIterator : public Iterator { 00241 public: 00244 PreorderIterator(T* node) : Iterator(node) {} 00245 virtual ~PreorderIterator() {} 00246 virtual Iterator& operator++(); 00247 00248 private: 00249 list<SparseTreeNode*> todo_; 00250 }; 00251 00252 00253 class PostorderIterator : public Iterator { 00254 public: 00257 PostorderIterator(T* node); 00258 virtual ~PostorderIterator() {} 00259 virtual Iterator& operator++(); 00260 00261 private: 00262 stack<SparseTreeNode*> todo_; 00263 stack<bool> visited_; 00264 }; 00265 00267 class BreadthFirstIterator : public Iterator { 00268 public: 00271 BreadthFirstIterator(T* node) : Iterator(node) {} 00272 virtual ~BreadthFirstIterator() {} 00273 virtual Iterator& operator++(); 00274 private: 00275 list<SparseTreeNode*> todo_; 00276 }; 00277 00278 private: 00279 T* root_node_; 00280 void DeleteLeafNode(SparseTreeNode* node); 00281 void FreeAllNodes(); 00282 00283 // Assumes my_node has no children (will not free any memory). 00284 // Makes my_node's children into a deep copy of other_node (copies 00285 // children and link structure as well). This will increment the 00286 // node count for each new bin added as well. It will NOT modify 00287 // my_node however. 00288 void CopySubtree(T** my_node, T* other_node); 00289 int num_nodes_; 00290 00291 // Block the copy assignment operator 00292 void operator=(const SparseTree<T>&); 00293 00294 // Static variable hacks so we don't have to always create end-iterators. 00295 static PreorderIterator end_preorder_; 00296 static PostorderIterator end_postorder_; 00297 static BreadthFirstIterator end_breadth_first_; 00298 }; 00299 } // namespace libpmk 00300 #endif // TREE_SPARSE_TREE_H