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_TREE_H 00009 #define TREE_TREE_H 00010 00011 #include <list> 00012 #include <stack> 00013 #include <ext/hash_map> 00014 #include "tree/tree-node.h" 00015 00016 using namespace std; 00017 using namespace __gnu_cxx; 00018 00019 namespace libpmk { 00020 00021 // TODO: clarify behavior when tree is empty. 00022 // Tree always has a root with ID 0. 00023 00026 00064 template <class T> 00065 class Tree { 00066 public: 00067 Tree(); 00068 ~Tree(); 00069 00072 Tree(const Tree<T>& other); 00073 00074 class Iterator; 00075 class PreorderIterator; 00076 class PostorderIterator; 00077 class BreadthFirstIterator; 00078 00080 void clear(); 00081 00083 T* root() { return tree_[0]; } 00084 const T* root() const { return node(0); } 00085 00087 int size() const { return tree_.size(); } 00088 00090 00093 T* node(int id); 00094 const T* node(int id) const; 00095 00097 00121 T* add_node(const T& new_node); 00122 00124 00131 T* add_node(); 00132 00133 00135 00143 void ReadFromStream(istream& input_stream); 00144 00146 00150 void WriteToStream(ostream& output_stream) const; 00151 00152 00154 void DeleteNode(int node_id); 00155 00157 PreorderIterator BeginPreorder() const; 00158 00160 const PreorderIterator& EndPreorder() const; 00161 00163 PostorderIterator BeginPostorder() const; 00164 00166 const PostorderIterator& EndPostorder() const; 00167 00169 BreadthFirstIterator BeginBreadthFirst() const; 00170 00172 const BreadthFirstIterator& EndBreadthFirst() const; 00173 00175 class Iterator { 00176 public: 00178 Iterator(int node_id, const Tree<T>* source_tree) : 00179 node_id_(node_id), source_tree_(source_tree) { } 00180 00181 virtual ~Iterator() { } 00182 00184 Iterator& operator=(const Iterator& other) { 00185 node_id_ = other.node_id_; 00186 return *this; 00187 } 00188 00190 bool operator==(const Iterator& other) { 00191 return node_id_ == other.node_id_; 00192 } 00193 00195 bool operator!=(const Iterator& other) { 00196 return node_id_ != other.node_id_; 00197 } 00198 00199 int operator*() { 00200 return node_id_; 00201 } 00202 00203 int id() { 00204 return node_id_; 00205 } 00206 00207 virtual Iterator& operator++() = 0; 00208 00209 protected: 00210 int node_id_; 00211 const Tree<T>* source_tree_; 00212 }; 00213 00214 00215 // Internally, we let <node_id_> be the current position. <todo_> 00216 // contains the IDs of all remaining nodes, but the nodes in <todo_> 00217 // may have yet to be expanded. 00219 class PreorderIterator : public Iterator { 00220 public: 00223 PreorderIterator(int node_id, const Tree<T>* tree) : 00224 Iterator(node_id, tree) { } 00225 virtual ~PreorderIterator() {} 00226 virtual Iterator& operator++(); 00227 00228 private: 00229 list<int> todo_; 00230 }; 00231 00232 class PostorderIterator : public Iterator { 00233 public: 00236 PostorderIterator(int node_id, const Tree<T>* tree); 00237 virtual ~PostorderIterator() {} 00238 virtual Iterator& operator++(); 00239 00240 private: 00241 stack<int> todo_; 00242 stack<bool> visited_; 00243 }; 00244 00246 class BreadthFirstIterator : public Iterator { 00247 public: 00250 BreadthFirstIterator(int node_id, const Tree<T>* tree) : 00251 Iterator(node_id, tree) {} 00252 virtual ~BreadthFirstIterator() {} 00253 virtual Iterator& operator++(); 00254 private: 00255 list<int> todo_; 00256 }; 00257 00258 private: 00259 hash_map<int, T*> tree_; 00260 int last_used_id_; 00261 00262 // Block the copy assignment operator 00263 void operator=(const Tree<T>&); 00264 00265 // Pre-create some end-iterators so we don't have to always create 00266 // them. This is useful for loops like: 00267 // while (iter != tree.EndPreorder()) 00268 // because calling this iterators generally involves instantiating 00269 // an STL stack, vector, or list. 00270 const PreorderIterator end_preorder_; 00271 const PostorderIterator end_postorder_; 00272 const BreadthFirstIterator end_breadth_first_; 00273 }; 00274 } // namespace libpmk 00275 00276 #endif // TREE_TREE_H