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