BinTree.h revision 5460a1f25d9ddecb5c70667267d66d51af177a99
1//===- BinTree.h ----------------------------------------------------------===//
2//
3//                     The MCLinker Project
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9#ifndef MCLD_BINARY_TREE_H
10#define MCLD_BINARY_TREE_H
11#ifdef ENABLE_UNITTEST
12#include <gtest.h>
13#endif
14
15#include "mcld/ADT/Uncopyable.h"
16#include "mcld/ADT/TreeAllocator.h"
17
18#include <iterator>
19#include <memory>
20#include <queue>
21#include <stack>
22
23namespace mcld
24{
25
26template<class DataType>
27class BinaryTree;
28
29class DFSIterator : public TreeIteratorBase
30{
31public:
32  DFSIterator()
33  : TreeIteratorBase()
34  { }
35
36  DFSIterator(NodeBase *X)
37    : TreeIteratorBase(X) {
38    if (hasRightChild())
39      m_Stack.push(m_pNode->right);
40    if (hasLeftChild())
41      m_Stack.push(m_pNode->left);
42  }
43
44  virtual ~DFSIterator()
45  { }
46
47  void advance() {
48    if (m_Stack.empty()) { // reach the end
49      m_pNode = m_pNode->right; // should be root
50      return;
51    }
52    m_pNode = m_Stack.top();
53    m_Stack.pop();
54    if (hasRightChild())
55      m_Stack.push(m_pNode->right);
56    if (hasLeftChild())
57      m_Stack.push(m_pNode->left);
58  }
59
60private:
61    std::stack<NodeBase *> m_Stack;
62};
63
64class BFSIterator : public TreeIteratorBase
65{
66public:
67  BFSIterator()
68  : TreeIteratorBase()
69  { }
70
71  BFSIterator(NodeBase *X)
72    : TreeIteratorBase(X) {
73    if (hasRightChild())
74      m_Queue.push(m_pNode->right);
75    if (hasLeftChild())
76      m_Queue.push(m_pNode->left);
77  }
78
79  virtual ~BFSIterator()
80  { }
81
82  void advance() {
83    if (m_Queue.empty()) { // reach the end
84      m_pNode = m_pNode->right; // should be root
85      return;
86    }
87    m_pNode = m_Queue.front();
88    m_Queue.pop();
89    if (hasRightChild())
90      m_Queue.push(m_pNode->right);
91    if (hasLeftChild())
92      m_Queue.push(m_pNode->left);
93  }
94
95private:
96    std::queue<NodeBase *> m_Queue;
97};
98
99template<class DataType, class Traits, class IteratorType>
100class PolicyIteratorBase : public IteratorType
101{
102public:
103  typedef DataType                       value_type;
104  typedef Traits                         traits;
105  typedef typename traits::pointer       pointer;
106  typedef typename traits::reference     reference;
107
108  typedef PolicyIteratorBase<value_type, Traits, IteratorType>          Self;
109  typedef Node<value_type>                                              node_type;
110  typedef typename traits::nonconst_traits                              nonconst_traits;
111  typedef PolicyIteratorBase<value_type, nonconst_traits, IteratorType> iterator;
112  typedef typename traits::const_traits                                 const_traits;
113  typedef PolicyIteratorBase<value_type, const_traits, IteratorType>    const_iterator;
114  typedef std::forward_iterator_tag                                     iterator_category;
115  typedef size_t                                                        size_type;
116  typedef ptrdiff_t                                                     difference_type;
117
118public:
119  PolicyIteratorBase()
120    : IteratorType() {}
121
122  PolicyIteratorBase(const iterator &X)
123    : IteratorType(X.m_pNode) {}
124
125  explicit PolicyIteratorBase(NodeBase* X)
126    : IteratorType(X) {}
127
128  virtual ~PolicyIteratorBase() {}
129
130  // -----  operators  ----- //
131  pointer operator*() const
132  { return static_cast<node_type*>(IteratorType::m_pNode)->data; }
133
134  reference operator->() const
135  { return *static_cast<node_type*>(IteratorType::m_pNode)->data; }
136
137  bool isRoot() const
138  { return (IteratorType::m_pNode->right == IteratorType::m_pNode); }
139
140  bool hasData() const
141  { return (!isRoot() && (0 != static_cast<node_type*>(IteratorType::m_pNode)->data)); }
142
143};
144
145template<class DataType, class Traits, class IteratorType>
146class PolicyIterator : public PolicyIteratorBase<DataType, Traits, IteratorType>
147{
148public:
149  typedef PolicyIterator<DataType, Traits, IteratorType> Self;
150  typedef PolicyIteratorBase<DataType, Traits, IteratorType> Base;
151  typedef PolicyIterator<DataType, typename Traits::nonconst_traits, IteratorType> iterator;
152  typedef PolicyIterator<DataType, typename Traits::const_traits, IteratorType>    const_iterator;
153
154public:
155  PolicyIterator()
156    : Base() {}
157
158  PolicyIterator(const iterator &X)
159    : Base(X.m_pNode) {}
160
161  explicit PolicyIterator(NodeBase* X)
162    : Base(X) {}
163
164  virtual ~PolicyIterator() {}
165
166  Self& operator++() {
167    IteratorType::advance();
168    return *this;
169  }
170
171  Self operator++(int) {
172    Self tmp = *this;
173    IteratorType::advance();
174    return tmp;
175  }
176};
177
178template<class DataType>
179class BinaryTree;
180
181/** \class TreeIterator
182 *  \brief TreeIterator provides full functions of binary tree's iterator.
183 *
184 *  TreeIterator is designed to compatible with STL iterators.
185 *  TreeIterator is bi-directional. Incremental direction means to move
186 *  rightward, and decremental direction is leftward.
187 *
188 *  @see TreeIteratorBase
189 */
190template<class DataType, class Traits>
191struct TreeIterator : public TreeIteratorBase
192{
193public:
194  typedef DataType                       value_type;
195  typedef Traits                         traits;
196  typedef typename traits::pointer       pointer;
197  typedef typename traits::reference     reference;
198
199  typedef TreeIterator<value_type, Traits>          Self;
200  typedef Node<value_type>                          node_type;
201
202  typedef typename traits::nonconst_traits          nonconst_traits;
203  typedef TreeIterator<value_type, nonconst_traits> iterator;
204  typedef typename traits::const_traits             const_traits;
205  typedef TreeIterator<value_type, const_traits>    const_iterator;
206  typedef std::bidirectional_iterator_tag           iterator_category;
207  typedef size_t                                    size_type;
208  typedef ptrdiff_t                                 difference_type;
209
210public:
211  TreeIterator()
212  : TreeIteratorBase() {}
213
214  TreeIterator(const iterator &X)
215    : TreeIteratorBase(X.m_pNode) {}
216
217  ~TreeIterator() {}
218
219  // -----  operators  ----- //
220  pointer operator*() const
221  { return static_cast<node_type*>(m_pNode)->data; }
222
223  reference operator->() const
224  { return *static_cast<node_type*>(m_pNode)->data; }
225
226  bool isRoot() const
227  { return (m_pNode->right == m_pNode); }
228
229  bool hasData() const
230  { return (!isRoot() && (0 != static_cast<node_type*>(m_pNode)->data)); }
231
232  Self& operator++() {
233    this->move<TreeIteratorBase::Rightward>();
234    return *this;
235  }
236
237  Self operator++(int) {
238    Self tmp = *this;
239    this->move<TreeIteratorBase::Rightward>();
240    return tmp;
241  }
242
243  Self& operator--() {
244    this->move<TreeIteratorBase::Leftward>();
245    return *this;
246  }
247
248  Self operator--(int) {
249    Self tmp = *this;
250    this->move<TreeIteratorBase::Leftward>();
251    return tmp;
252  }
253
254  explicit TreeIterator(NodeBase* X)
255    : TreeIteratorBase(X) {}
256};
257
258/** \class BinaryTreeBase
259 *  \brief BinaryTreeBase gives root node and memory management.
260 *
261 *  The memory management of nodes in is hidden by BinaryTreeBase.
262 *  BinaryTreeBase also provides the basic functions for merging a tree and
263 *  inserton of a node.
264 *
265 *  @see BinaryTree
266 */
267template<class DataType>
268class BinaryTreeBase : private Uncopyable
269{
270public:
271  typedef Node<DataType> NodeType;
272protected:
273  /// TreeImpl - TreeImpl records the root node and the number of nodes
274  //
275  //    +---> Root(end) <---+
276  //    |        |left      |
277  //    |      begin        |
278  //    |     /     \       |
279  //    |  Left     Right   |
280  //    +---/         \-----+
281  //
282  class TreeImpl : public NodeFactory<DataType>
283  {
284    typedef typename NodeFactory<DataType>::iterator       iterator;
285    typedef typename NodeFactory<DataType>::const_iterator const_iterator;
286
287  public:
288    NodeBase node;
289
290  public:
291    TreeImpl()
292      : NodeFactory<DataType>() {
293      node.left = node.right = &node;
294    }
295
296    ~TreeImpl()
297    { }
298
299    /// summon - change the final edges of pClient to our root
300    void summon(TreeImpl& pClient) {
301      if (this == &pClient)
302        return;
303
304      iterator data;
305      iterator dEnd = pClient.end();
306      for (data = pClient.begin(); data!=dEnd; ++data ) {
307        if ((*data).left == &pClient.node)
308          (*data).left = &node;
309        if ((*data).right == &pClient.node)
310          (*data).right = &node;
311      }
312    }
313  }; // TreeImpl
314
315protected:
316  /// m_Root is a special object who responses:
317  //  - the pointer of root
318  //  - the simple factory of nodes.
319  TreeImpl m_Root;
320
321protected:
322  NodeType *createNode() {
323    NodeType *result = m_Root.produce();
324    result->left = result->right = &m_Root.node;
325    return result;
326  }
327
328  void destroyNode(NodeType *pNode) {
329    pNode->left = pNode->right = 0;
330    pNode->data = 0;
331    m_Root.deallocate(pNode);
332  }
333
334public:
335  BinaryTreeBase()
336  : m_Root()
337  { }
338
339  virtual ~BinaryTreeBase()
340  { }
341
342  size_t size() const {
343    return m_Root.size();
344  }
345
346  bool empty() const {
347    return m_Root.empty();
348  }
349
350protected:
351  void clear() {
352    m_Root.clear();
353  }
354};
355
356/** \class BinaryTree
357 *  \brief An abstract data type of binary tree.
358 *
359 *  @see mcld::InputTree
360 */
361template<class DataType>
362class BinaryTree : public BinaryTreeBase<DataType>
363{
364public:
365  typedef size_t             size_type;
366  typedef ptrdiff_t          difference_type;
367  typedef DataType           value_type;
368  typedef value_type*        pointer;
369  typedef value_type&        reference;
370  typedef const value_type*  const_pointer;
371  typedef const value_type&  const_reference;
372
373  typedef BinaryTree<DataType>  Self;
374  typedef TreeIterator<value_type, NonConstTraits<value_type> > iterator;
375  typedef TreeIterator<value_type, ConstTraits<value_type> >    const_iterator;
376
377  typedef PolicyIterator<value_type, NonConstTraits<value_type>, DFSIterator> dfs_iterator;
378  typedef PolicyIterator<value_type, ConstTraits<value_type>, DFSIterator>    const_dfs_iterator;
379  typedef PolicyIterator<value_type, NonConstTraits<value_type>, BFSIterator> bfs_iterator;
380  typedef PolicyIterator<value_type, ConstTraits<value_type>, BFSIterator>    const_bfs_iterator;
381
382protected:
383  typedef Node<value_type> node_type;
384
385public:
386  // -----  constructors and destructor  ----- //
387  BinaryTree()
388  : BinaryTreeBase<DataType>()
389  { }
390
391  ~BinaryTree() {
392  }
393
394  // -----  iterators  ----- //
395  bfs_iterator bfs_begin()
396  { return bfs_iterator(BinaryTreeBase<DataType>::m_Root.node.left); }
397
398  bfs_iterator bfs_end()
399  { return bfs_iterator(BinaryTreeBase<DataType>::m_Root.node.right); }
400
401  const_bfs_iterator bfs_begin() const
402  { return const_bfs_iterator(BinaryTreeBase<DataType>::m_Root.node.left); }
403
404  const_bfs_iterator bfs_end() const
405  { return const_bfs_iterator(BinaryTreeBase<DataType>::m_Root.node.right); }
406
407  dfs_iterator dfs_begin()
408  { return dfs_iterator(BinaryTreeBase<DataType>::m_Root.node.left); }
409
410  dfs_iterator dfs_end()
411  { return dfs_iterator(BinaryTreeBase<DataType>::m_Root.node.right); }
412
413  const_dfs_iterator dfs_begin() const
414  { return const_dfs_iterator(BinaryTreeBase<DataType>::m_Root.node.left); }
415
416  const_dfs_iterator dfs_end() const
417  { return const_dfs_iterator(BinaryTreeBase<DataType>::m_Root.node.right); }
418
419  iterator root()
420  { return iterator(&(BinaryTreeBase<DataType>::m_Root.node)); }
421
422  const_iterator root() const
423  { return const_iterator(&(BinaryTreeBase<DataType>::m_Root.node)); }
424
425  iterator begin()
426  { return iterator(BinaryTreeBase<DataType>::m_Root.node.left); }
427
428  iterator end()
429  { return iterator(BinaryTreeBase<DataType>::m_Root.node.right); }
430
431  const_iterator begin() const
432  { return const_iterator(BinaryTreeBase<DataType>::m_Root.node.left); }
433
434  const_iterator end() const
435  { return const_iterator(BinaryTreeBase<DataType>::m_Root.node.right); }
436
437  // ----- modifiers  ----- //
438  /// join - create a leaf node and merge it in the tree.
439  //  This version of join determines the direction on compilation time.
440  //  @param DIRECT the direction of the connecting edge of the parent node.
441  //  @param position the parent node
442  //  @param value the value being pushed.
443  template<size_t DIRECT, class Pos>
444  BinaryTree& join(Pos position, const DataType& value) {
445    node_type *node = BinaryTreeBase<DataType>::createNode();
446    node->data = const_cast<DataType*>(&value);
447    if (position.isRoot())
448      proxy::hook<TreeIteratorBase::Leftward>(position.m_pNode,
449                          const_cast<const node_type*>(node));
450    else
451      proxy::hook<DIRECT>(position.m_pNode,
452                          const_cast<const node_type*>(node));
453    return *this;
454  }
455
456  /// merge - merge the tree
457  //  @param DIRECT the direction of the connecting edge of the parent node.
458  //  @param position the parent node
459  //  @param the tree being joined.
460  //  @return the joined tree
461  template<size_t DIRECT, class Pos>
462  BinaryTree& merge(Pos position, BinaryTree& pTree) {
463    if (this == &pTree)
464      return *this;
465
466    if (!pTree.empty()) {
467      proxy::hook<DIRECT>(position.m_pNode,
468                        const_cast<const NodeBase*>(pTree.m_Root.node.left));
469      BinaryTreeBase<DataType>::m_Root.summon(
470                                   pTree.BinaryTreeBase<DataType>::m_Root);
471      BinaryTreeBase<DataType>::m_Root.delegate(pTree.m_Root);
472      pTree.m_Root.node.left = pTree.m_Root.node.right = &pTree.m_Root.node;
473    }
474    return *this;
475  }
476};
477
478} // namespace of mcld
479
480#endif
481
482