aimstil  5.0.5
binary_tree.h
Go to the documentation of this file.
1 #ifndef _BINARYTREE_H_
2 #define _BINARYTREE_H_
3 
4 // includes from STL
5 #include <list>
6 #include <queue>
7 #include <set>
8 
9 // includes from BOOST
10 #include <boost/array.hpp>
11 #include <boost/type_traits.hpp>
12 #include <boost/utility/enable_if.hpp>
13 
14 // includes from TIL
15 #include "globalTraits.h"
16 
17 namespace til
18 {
19 
20  //---------------------------------------------------------------------------
21 
22  //------------//
23  // NaryTree //
24  //------------//
25 
39  template < typename T, std::size_t N >
40  class NaryTree
41  {
42  public: // exceptions -------------------------------------------------------
43 
44  class TreeRootAlreadyDefined : public std::exception {};
45 
46  public: // classes ----------------------------------------------------------
47 
48  class iterator;
49  class const_iterator;
50 
51  private: // classes ---------------------------------------------------------
52 
53  template < typename X > class iterator_base;
54  class Node;
55  struct Destructor;
56 
57  public: // constructors & destructor ----------------------------------------
58 
60  NaryTree() : m_root(), m_size() {}
61 
63  ~NaryTree();
64 
65  public: // set & get --------------------------------------------------------
66 
67  std::size_t size() const { return m_size; }
68 
69  public: // functions --------------------------------------------------------
70 
72  const_iterator
73  root() const;
74 
76  iterator
77  root();
78 
80  iterator
81  addChild
82  (
83  Node * parent
84  , std::size_t childNumber
85  , T value = T()
86  );
87 
89  iterator
90  addChild
91  (
92  iterator & parent
93  , std::size_t childNumber
94  , T value = T()
95  );
96 
97  private: // data ------------------------------------------------------------
98 
99  Node * m_root;
100  std::size_t m_size;
101  };
102 
103 
104  //---------------------------------------------------------------------------
105 
106  //------------------//
107  // NaryTree::Node //
108  //------------------//
109 
115  template < typename T, std::size_t N >
116  class NaryTree<T,N>::Node
117  {
118  public: // typedefs ---------------------------------------------------------
119 
120  typedef T value_type;
121 
122  public: // constructors -----------------------------------------------------
123 
125  Node() :
126  m_value()
127  , m_branch()
128  {
129  m_branch.assign(0);
130  }
131 
133  explicit Node(const T & value) :
134  m_value(value)
135  , m_branch()
136  {
137  m_branch.assign(0);
138  }
139 
140  public: // set & get --------------------------------------------------------
141 
142  const T & operator()() const { return m_value; }
143  T & operator()() { return m_value; }
144 
145  const T & get() const { return m_value; }
146  T & get() { return m_value; }
147 
149  Node * child(std::size_t i) const
150  {
151  assert(i < til::size(m_branch));
152  return m_branch[i];
153  }
154 
156  Node * & child(std::size_t i)
157  {
158  assert(i < til::size(m_branch));
159  return m_branch[i];
160  }
161 
162  void operator=(const T & value) { m_value = value; }
163 
164  private: // data ------------------------------------------------------------
165 
166  // Index to the current value
167  T m_value;
168  // pointers to branches
169  boost::array<Node*, N> m_branch;
170  };
171 
172 
173  //---------------------------------------------------------------------------
174 
175  //---------------------------//
176  // NaryTree::iterator_base //
177  //---------------------------//
178 
181  template < typename T, std::size_t N >
182  // NB: It is understood that X is a Node
183  template < typename X >
184  class NaryTree<T,N>::iterator_base
185  {
186  public: // typedefs
187  typedef iterator_base<X> Self;
188  typedef typename X::value_type value_type;
189 
190  public: // constructors & destructor ----------------------------------------
191 
192  iterator_base() {}
193  explicit iterator_base(X * pNode) : m_pNode(pNode) {}
194 
195  public: // functions --------------------------------------------------------
196 
198  const value_type & operator*() const { return m_pNode->get(); }
199  const value_type * operator->() const { return &(m_pNode->get()); }
200 
202  operator X*() { return m_pNode; }
203  X * node() const { return m_pNode; }
204 
205  public: // static functions -------------------------------------------------
206 
207  static std::size_t nchildren() { return N; }
208 
209  protected: // functions -----------------------------------------------------
210 
211  X * child(std::size_t i) const { return this->node()->child(i); }
212 
213  protected: // data ----------------------------------------------------------
214 
215  X * m_pNode;
216  };
217 
218  //---------------------------------------------------------------------------
219 
220  //----------------------------//
221  // NaryTree::const_iterator //
222  //----------------------------//
223 
227  template < typename T, std::size_t N >
228  //class NaryTree<T,N>::const_iterator : public iterator_base<const Node>
229  class NaryTree<T,N>::const_iterator : public NaryTree<T,N>::template iterator_base<const Node>
230  {
231  public: // typedefs ---------------------------------------------------------
232 
234  typedef iterator_base<const Node> Base;
235  typedef typename Base::value_type value_type;
236 
237  public: // constructors -----------------------------------------------------
238 
239  // NB: default constructor set const_iterator to zero
240  const_iterator() : Base() {}
241  explicit const_iterator(const Node * p) : Base(p) {}
242 
243  public: // functions --------------------------------------------------------
244 
246  Self child(std::size_t i) const { return Self(this->Base::child(i)); }
247  };
248 
249  //---------------------------------------------------------------------------
250 
251  //----------------------//
252  // NaryTree::iterator //
253  //----------------------//
254 
260  // TODO: get rid of code duplication with const_iterator if possible.
261  // TODO: the advertising of parent() and branch() is not cool -- this is more of
262  // an internal stuff.
263  template < typename T, std::size_t N >
264  class NaryTree<T,N>::iterator : public NaryTree<T,N>::template iterator_base<Node>
265  {
266  public: // typedefs ---------------------------------------------------------
267 
268  typedef iterator_base<Node> Base;
269  typedef typename Base::value_type value_type;
270 
271  public: // constructors -----------------------------------------------------
272 
273  // NB: default constructor set iterator to zero
274  iterator() : Base(), m_parent() {}
275  iterator(Node * p) : Base(p) {}
276  iterator(Node * p, Node * parent, std::size_t branch) : Base(p), m_parent(parent), m_branch(branch) {}
277  //iterator(const iterator &i) : TCollection::iterator(i) {}
278 
279  public: // functions --------------------------------------------------------
280 
282  //operator Node* () { return &**this; }
283 
284  iterator child(std::size_t i) const
285  {
286  // NB: no need to assert here, as it is done in Node
287  return iterator(this->node()->child(i), this->node(), 0);
288  }
289 
290  std::size_t branch() const { return m_branch; }
291 
292  Node * parent() const { return m_parent; }
293 
294  value_type & operator*() { return this->m_pNode->get(); }
295  value_type * operator->() { return &(this->m_pNode->get()); }
296 
297  private: // data ------------------------------------------------------------
298 
299  // The private information of the non-const iterator contains information
300  // necessary in case of a new allocation, i.e. its relation with its parent.
301 
302  // Pointer on the parent
303  Node * m_parent;
304  // Branch number on which we lie.
305  std::size_t m_branch;
306  };
307 
308  template < typename T, std::size_t N >
309  inline
310  std::size_t
311  size(const NaryTree<T,N> & ntree) { return ntree.size(); }
312 
313 
314  //---------------------------------------------------------------------------
315 
316  //-----------------------------//
317  // inline methods and structs //
318  //-----------------------------//
319 
320  template < typename T, std::size_t N >
321  struct NaryTree<T, N>::Destructor
322  {
323  void operator()(iterator i) const { delete &*i; }
324  };
325 
326  template < typename T, std::size_t N >
327  inline typename NaryTree<T, N>::const_iterator
329  { return const_iterator(m_root); }
330 
331  template < typename T, std::size_t N >
332  inline typename NaryTree<T, N>::iterator
334  { return iterator(m_root, 0, 0); }
335 
336  template < typename T, std::size_t N >
337  inline typename NaryTree<T, N>::iterator
339  (
340  iterator & parent
341  , std::size_t childNumber
342  , T value
343  )
344  { return this->addChild(parent.node(), childNumber, value); }
345 
346 
347  //---------------------------------------------------------------------------
348 
349  //------------------------//
350  // functors and helpers //
351  //------------------------//
352 
353 
354 
355  namespace treeFunctors
356  {
357  // a dummy functor to test tree traversals.
358  template < typename TTreeIterator >
359  class Count
360  {
361  public: // constructors & destructor
362  Count() : m_count() {}
363 
364  public: // functions
365  static bool leftFirst() { return true; }
366  static bool left() { return true; }
367  static bool right() { return true; }
368 
369  void operator()(const TTreeIterator &) { ++m_count; }
370  std::size_t operator()() { return m_count; }
371 
372  private:
373  std::size_t m_count;
374  };
375  }
376 
377 
378  //---------------------------------------------------------------------------
379 
384  template < typename TTreeIterator, typename TTreeFunctor >
385  void pre_order_scan(TTreeIterator iTree, TTreeFunctor & f)
386  {
387  f(iTree);
388  for (std::size_t i=0; i < iTree.nchildren(); ++i)
389  {
390  if (&*(iTree.child(i))) pre_order_scan(iTree.child(i), f);
391  }
392  }
393 
394  //---------------------------------------------------------------------------
395 
399  template < typename TTreeIterator, typename TTreeFunctor >
400  void post_order_scan(TTreeIterator iTree, const TTreeFunctor & f)
401  {
402  for (std::size_t i=0; i < iTree.nchildren(); ++i)
403  {
404  if (&*(iTree.child(i))) post_order_scan(iTree.child(i), f);
405  }
406  f(iTree);
407  }
408 
409  //---------------------------------------------------------------------------
410 
414  template < typename TTreeIterator, typename TTreeFunctor >
415  void
416  in_order_scan(TTreeIterator iTree, const TTreeFunctor & f)
417  {
418  while (iTree)
419  {
420  if (&*(iTree.child(0))) in_order_scan(iTree->child(0));
421  f(iTree);
422  iTree = iTree.child(1);
423  }
424  }
425 
426  //---------------------------------------------------------------------------
427 
428  namespace detail
429  {
430  template < typename TTreeIterator, typename TBFFunctor >
431  void breadth_first(std::queue<TTreeIterator> q, const TBFFunctor & f)
432  {
433  std::queue<TTreeIterator> newQ;
434  while (!q.empty())
435  {
436  f(q.front());
437  for (std::size_t i = 0; i < q.front().nchildren(); ++i)
438  {
439  if (q.front().child(i)) newQ.push(q.front().child(i));
440  }
441  q.pop();
442  }
443  if (!newQ.empty())
444  {
445  // warn functor that we are about to go to the next level
446  f.nextLevel();
447  // iterate
448  breadth_first(newQ, f);
449  }
450  }
451  } // namespace detail
452 
453  //---------------------------------------------------------------------------
454 
458  template < typename TTreeIterator, typename TBFFunctor >
459  void breadth_first(TTreeIterator iTree, const TBFFunctor & f)
460  {
461  // Do nothing if nothing to be done.
462  if (!&*iTree) return;
463  // Here, we simply construct a queue containing a single element, and call
464  // the appropriate version of breadth_first.
465  std::queue<TTreeIterator> q;
466  q.push(iTree);
467  detail::breadth_first(q, f);
468  }
469 
470  //---------------------------------------------------------------------------
471 
472  namespace detail
473  {
475  struct Print
476  {
478  static void nextLevel() { std::cout << std::endl; }
479 
480  template < typename TIterator >
481  void operator()(const TIterator & i) const
482  {
483  if (&*i)
484  {
485  std::cout << *i << " , ";
486  }
487  else
488  {
489  std::cout << " [X] , ";
490  }
491  }
492  };
493  } // namespace detail
494 
495  //---------------------------------------------------------------------------
496 
498  template < typename T, std::size_t N >
499  void print(const NaryTree<T,N> & tree)
500  {
501  breadth_first(tree.root(), detail::Print());
502  }
503 
504  //---------------------------------------------------------------------------
505 
506 } // namespace til
507 
508 // package include
509 #include "binary_tree.tpp"
510 
511 #endif //_BINARYTREE_H_
Base::value_type value_type
Definition: binary_tree.h:269
Node(const T &value)
Constructor with a single value: collect value and set branches to zero.
Definition: binary_tree.h:133
Base::value_type value_type
Definition: binary_tree.h:235
std::size_t size() const
Definition: binary_tree.h:67
iterator(Node *p, Node *parent, std::size_t branch)
Definition: binary_tree.h:276
NaryTree()
Default constructor builds an emtpy tree.
Definition: binary_tree.h:60
std::size_t branch() const
Definition: binary_tree.h:290
Const iterator on n-ary trees.
Definition: binary_tree.h:229
~NaryTree()
Destructor.
void print(const Affine< T > &a)
iterator_base< const Node > Base
Definition: binary_tree.h:234
std::size_t operator()()
Definition: binary_tree.h:370
void post_order_scan(TTreeIterator iTree, const TTreeFunctor &f)
Post-order scan.
Definition: binary_tree.h:400
void breadth_first(std::queue< TTreeIterator > q, const TBFFunctor &f)
Definition: binary_tree.h:431
Belongs to package Box Do not include directly, include til/Box.h instead.
Definition: Accumulator.h:10
void breadth_first(TTreeIterator iTree, const TBFFunctor &f)
Apply a functor in a breadth-first traversal order, starting from the iterator given in input...
Definition: binary_tree.h:459
value_type * operator->()
Definition: binary_tree.h:295
numeric_array< T, D > size(const Box< T, D > &box)
Return the size of a box.
Definition: boxTools.h:56
void operator()(const TIterator &i) const
Definition: binary_tree.h:481
Self child(std::size_t i) const
Get an iterator on the i-th child.
Definition: binary_tree.h:246
Internal class used inside binary tree.
Definition: binary_tree.h:116
void operator()(iterator i) const
Definition: binary_tree.h:323
static bool leftFirst()
Definition: binary_tree.h:365
INLINE numeric_array< typename combine< T1, T2 >::type, 3 > operator*(const Affine< T1 > &a, const numeric_array< T2, 3 > &v)
Multiplication between a 3D affine transform and a 3D vector.
iterator_base< Node > Base
Definition: binary_tree.h:268
Node()
Default constructor, set everything to zero.
Definition: binary_tree.h:125
void pre_order_scan(TTreeIterator iTree, TTreeFunctor &f)
Pre-order scan.
Definition: binary_tree.h:385
void operator=(const T &value)
Definition: binary_tree.h:162
value_type & operator*()
Definition: binary_tree.h:294
void operator()(const TTreeIterator &)
Definition: binary_tree.h:369
Node *& child(std::size_t i)
Returns a pointer on the n-th child.
Definition: binary_tree.h:156
iterator addChild(Node *parent, std::size_t childNumber, T value=T())
Add a child to a node.
Non-const iterator on n-ary trees.
Definition: binary_tree.h:264
Breadth-first tree functor to print out tree.
Definition: binary_tree.h:475
void in_order_scan(TTreeIterator iTree, const TTreeFunctor &f)
In-order scan.
Definition: binary_tree.h:416
static void nextLevel()
Function called at.
Definition: binary_tree.h:478
A class to represent an N-ary tree.
Node * parent() const
Definition: binary_tree.h:292
iterator child(std::size_t i) const
Convertion into a Node pointer.
Definition: binary_tree.h:284
const_iterator root() const
Return a const iterator on the root element of the tree.
Definition: binary_tree.h:328
Node * child(std::size_t i) const
Returns a pointer on the n-th child.
Definition: binary_tree.h:149
const T & operator()() const
Definition: binary_tree.h:142