//===- BinTree.h ----------------------------------------------------------===// // // The MCLinker Project // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef MCLD_ADT_BINTREE_H_ #define MCLD_ADT_BINTREE_H_ #include "mcld/ADT/TreeAllocator.h" #include "mcld/ADT/TreeBase.h" #include "mcld/Support/Compiler.h" #include #include #include #include #include namespace mcld { template class BinaryTree; class DFSIterator : public TreeIteratorBase { public: DFSIterator() : TreeIteratorBase() {} explicit DFSIterator(NodeBase* X) : TreeIteratorBase(X) { if (hasRightChild()) m_Stack.push(m_pNode->right); if (hasLeftChild()) m_Stack.push(m_pNode->left); } virtual ~DFSIterator() {} void advance() { if (m_Stack.empty()) { // reach the end m_pNode = m_pNode->right; // should be root return; } m_pNode = m_Stack.top(); m_Stack.pop(); if (hasRightChild()) m_Stack.push(m_pNode->right); if (hasLeftChild()) m_Stack.push(m_pNode->left); } private: std::stack m_Stack; }; class BFSIterator : public TreeIteratorBase { public: BFSIterator() : TreeIteratorBase() {} explicit BFSIterator(NodeBase* X) : TreeIteratorBase(X) { if (hasRightChild()) m_Queue.push(m_pNode->right); if (hasLeftChild()) m_Queue.push(m_pNode->left); } virtual ~BFSIterator() {} void advance() { if (m_Queue.empty()) { // reach the end m_pNode = m_pNode->right; // should be root return; } m_pNode = m_Queue.front(); m_Queue.pop(); if (hasRightChild()) m_Queue.push(m_pNode->right); if (hasLeftChild()) m_Queue.push(m_pNode->left); } private: std::queue m_Queue; }; template class PolicyIteratorBase : public IteratorType { public: typedef DataType value_type; typedef Traits traits; typedef typename traits::pointer pointer; typedef typename traits::reference reference; typedef PolicyIteratorBase Self; typedef Node node_type; typedef typename traits::nonconst_traits nonconst_traits; typedef typename traits::const_traits const_traits; typedef PolicyIteratorBase iterator; typedef PolicyIteratorBase const_iterator; typedef std::forward_iterator_tag iterator_category; typedef size_t size_type; typedef ptrdiff_t difference_type; public: PolicyIteratorBase() : IteratorType() {} PolicyIteratorBase(const iterator& X) : IteratorType(X.m_pNode) {} explicit PolicyIteratorBase(NodeBase* X) : IteratorType(X) {} virtual ~PolicyIteratorBase() {} // ----- operators ----- // pointer operator*() const { return static_cast(IteratorType::m_pNode)->data; } reference operator->() const { return *static_cast(IteratorType::m_pNode)->data; } bool hasData() const { return (!IteratorType::isRoot() && (0 != static_cast(IteratorType::m_pNode)->data)); } }; template class PolicyIterator : public PolicyIteratorBase { public: typedef PolicyIterator Self; typedef PolicyIteratorBase Base; typedef PolicyIterator iterator; typedef PolicyIterator const_iterator; public: PolicyIterator() : Base() {} PolicyIterator(const iterator& X) : Base(X.m_pNode) {} explicit PolicyIterator(NodeBase* X) : Base(X) {} virtual ~PolicyIterator() {} Self& operator++() { IteratorType::advance(); return *this; } Self operator++(int) { Self tmp = *this; IteratorType::advance(); return tmp; } }; template class BinaryTree; /** \class TreeIterator * \brief TreeIterator provides full functions of binary tree's iterator. * * TreeIterator is designed to compatible with STL iterators. * TreeIterator is bi-directional. Incremental direction means to move * rightward, and decremental direction is leftward. * * @see TreeIteratorBase */ template struct TreeIterator : public TreeIteratorBase { public: typedef DataType value_type; typedef Traits traits; typedef typename traits::pointer pointer; typedef typename traits::reference reference; typedef TreeIterator Self; typedef Node node_type; typedef typename traits::nonconst_traits nonconst_traits; typedef TreeIterator iterator; typedef typename traits::const_traits const_traits; typedef TreeIterator const_iterator; typedef std::bidirectional_iterator_tag iterator_category; typedef size_t size_type; typedef ptrdiff_t difference_type; public: TreeIterator() : TreeIteratorBase() {} TreeIterator(const iterator& X) : TreeIteratorBase(X.m_pNode) {} ~TreeIterator() {} // ----- operators ----- // pointer operator*() const { return static_cast(m_pNode)->data; } reference operator->() const { return *static_cast(m_pNode)->data; } bool isRoot() const { return (m_pNode->right == m_pNode); } bool hasData() const { return (!isRoot() && (0 != static_cast(m_pNode)->data)); } Self& operator++() { this->move(); return *this; } Self operator++(int) { Self tmp = *this; this->move(); return tmp; } Self& operator--() { this->move(); return *this; } Self operator--(int) { Self tmp = *this; this->move(); return tmp; } explicit TreeIterator(NodeBase* X) : TreeIteratorBase(X) {} }; /** \class BinaryTreeBase * \brief BinaryTreeBase gives root node and memory management. * * The memory management of nodes in is hidden by BinaryTreeBase. * BinaryTreeBase also provides the basic functions for merging a tree and * inserton of a node. * * @see BinaryTree */ template class BinaryTreeBase { public: typedef Node NodeType; protected: /// TreeImpl - TreeImpl records the root node and the number of nodes // // +---> Root(end) <---+ // | |left | // | begin | // | / \ | // | Left Right | // +---/ \-----+ // class TreeImpl : public NodeFactory { typedef typename NodeFactory::iterator iterator; typedef typename NodeFactory::const_iterator const_iterator; public: NodeBase node; public: TreeImpl() : NodeFactory() { node.left = node.right = &node; } ~TreeImpl() {} /// summon - change the final edges of pClient to our root void summon(TreeImpl& pClient) { if (this == &pClient) return; iterator data; iterator dEnd = pClient.end(); for (data = pClient.begin(); data != dEnd; ++data) { if ((*data).left == &pClient.node) (*data).left = &node; if ((*data).right == &pClient.node) (*data).right = &node; } } }; // TreeImpl protected: /// m_Root is a special object who responses: // - the pointer of root // - the simple factory of nodes. TreeImpl m_Root; protected: NodeType* createNode() { NodeType* result = m_Root.produce(); result->left = result->right = &m_Root.node; return result; } void destroyNode(NodeType* pNode) { pNode->left = pNode->right = 0; pNode->data = 0; m_Root.deallocate(pNode); } public: BinaryTreeBase() : m_Root() {} virtual ~BinaryTreeBase() {} size_t size() const { return m_Root.size(); } bool empty() const { return m_Root.empty(); } protected: void clear() { m_Root.clear(); } private: DISALLOW_COPY_AND_ASSIGN(BinaryTreeBase); }; /** \class BinaryTree * \brief An abstract data type of binary tree. * * @see mcld::InputTree */ template class BinaryTree : public BinaryTreeBase { public: typedef size_t size_type; typedef ptrdiff_t difference_type; typedef DataType value_type; typedef value_type* pointer; typedef value_type& reference; typedef const value_type* const_pointer; typedef const value_type& const_reference; typedef BinaryTree Self; typedef TreeIterator > iterator; typedef TreeIterator > const_iterator; typedef PolicyIterator, DFSIterator> dfs_iterator; typedef PolicyIterator, DFSIterator> const_dfs_iterator; typedef PolicyIterator, BFSIterator> bfs_iterator; typedef PolicyIterator, BFSIterator> const_bfs_iterator; protected: typedef Node node_type; public: // ----- constructors and destructor ----- // BinaryTree() : BinaryTreeBase() {} ~BinaryTree() {} // ----- iterators ----- // bfs_iterator bfs_begin() { return bfs_iterator(BinaryTreeBase::m_Root.node.left); } bfs_iterator bfs_end() { return bfs_iterator(BinaryTreeBase::m_Root.node.right); } const_bfs_iterator bfs_begin() const { return const_bfs_iterator(BinaryTreeBase::m_Root.node.left); } const_bfs_iterator bfs_end() const { return const_bfs_iterator(BinaryTreeBase::m_Root.node.right); } dfs_iterator dfs_begin() { return dfs_iterator(BinaryTreeBase::m_Root.node.left); } dfs_iterator dfs_end() { return dfs_iterator(BinaryTreeBase::m_Root.node.right); } const_dfs_iterator dfs_begin() const { return const_dfs_iterator(BinaryTreeBase::m_Root.node.left); } const_dfs_iterator dfs_end() const { return const_dfs_iterator(BinaryTreeBase::m_Root.node.right); } iterator root() { return iterator(&(BinaryTreeBase::m_Root.node)); } const_iterator root() const { return const_iterator(&(BinaryTreeBase::m_Root.node)); } iterator begin() { return iterator(BinaryTreeBase::m_Root.node.left); } iterator end() { return iterator(BinaryTreeBase::m_Root.node.right); } const_iterator begin() const { return const_iterator(BinaryTreeBase::m_Root.node.left); } const_iterator end() const { return const_iterator(BinaryTreeBase::m_Root.node.right); } // ----- modifiers ----- // /// join - create a leaf node and merge it in the tree. // This version of join determines the direction on compilation time. // @param DIRECT the direction of the connecting edge of the parent node. // @param position the parent node // @param value the value being pushed. template BinaryTree& join(TreeIteratorBase& pPosition, const DataType& pValue) { node_type* node = BinaryTreeBase::createNode(); node->data = const_cast(&pValue); if (pPosition.isRoot()) pPosition.hook(node); else pPosition.hook(node); return *this; } /// merge - merge the tree // @param DIRECT the direction of the connecting edge of the parent node. // @param position the parent node // @param the tree being joined. // @return the joined tree template BinaryTree& merge(TreeIteratorBase& pPosition, BinaryTree& pTree) { if (this == &pTree) return *this; if (!pTree.empty()) { pPosition.hook(pTree.m_Root.node.left); BinaryTreeBase::m_Root.summon( pTree.BinaryTreeBase::m_Root); BinaryTreeBase::m_Root.delegate(pTree.m_Root); pTree.m_Root.node.left = pTree.m_Root.node.right = &pTree.m_Root.node; } return *this; } }; } // namespace mcld #endif // MCLD_ADT_BINTREE_H_