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