//===- BinTree.h ----------------------------------------------------------===// // // The MCLinker Project // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef MCLD_BINARY_TREE_H #define MCLD_BINARY_TREE_H #ifdef ENABLE_UNITTEST #include <gtest.h> #endif #include <mcld/ADT/Uncopyable.h> #include <mcld/ADT/TreeBase.h> #include <mcld/ADT/TreeAllocator.h> #include <cstddef> #include <iterator> #include <memory> #include <queue> #include <stack> namespace mcld { template<class DataType> class BinaryTree; class DFSIterator : public TreeIteratorBase { public: DFSIterator() : TreeIteratorBase() { } 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<NodeBase *> m_Stack; }; class BFSIterator : public TreeIteratorBase { public: BFSIterator() : TreeIteratorBase() { } 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<NodeBase *> m_Queue; }; template<class DataType, class Traits, class IteratorType> class PolicyIteratorBase : public IteratorType { public: typedef DataType value_type; typedef Traits traits; typedef typename traits::pointer pointer; typedef typename traits::reference reference; typedef PolicyIteratorBase<value_type, Traits, IteratorType> Self; typedef Node<value_type> node_type; typedef typename traits::nonconst_traits nonconst_traits; typedef PolicyIteratorBase<value_type, nonconst_traits, IteratorType> iterator; typedef typename traits::const_traits const_traits; typedef PolicyIteratorBase<value_type, const_traits, IteratorType> 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<node_type*>(IteratorType::m_pNode)->data; } reference operator->() const { return *static_cast<node_type*>(IteratorType::m_pNode)->data; } bool hasData() const { return (!IteratorType::isRoot() && (0 != static_cast<node_type*>(IteratorType::m_pNode)->data)); } }; template<class DataType, class Traits, class IteratorType> class PolicyIterator : public PolicyIteratorBase<DataType, Traits, IteratorType> { public: typedef PolicyIterator<DataType, Traits, IteratorType> Self; typedef PolicyIteratorBase<DataType, Traits, IteratorType> Base; typedef PolicyIterator<DataType, typename Traits::nonconst_traits, IteratorType> iterator; typedef PolicyIterator<DataType, typename Traits::const_traits, IteratorType> 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 DataType> 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<class DataType, class Traits> struct TreeIterator : public TreeIteratorBase { public: typedef DataType value_type; typedef Traits traits; typedef typename traits::pointer pointer; typedef typename traits::reference reference; typedef TreeIterator<value_type, Traits> Self; typedef Node<value_type> node_type; typedef typename traits::nonconst_traits nonconst_traits; typedef TreeIterator<value_type, nonconst_traits> iterator; typedef typename traits::const_traits const_traits; typedef TreeIterator<value_type, const_traits> 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<node_type*>(m_pNode)->data; } reference operator->() const { return *static_cast<node_type*>(m_pNode)->data; } bool isRoot() const { return (m_pNode->right == m_pNode); } bool hasData() const { return (!isRoot() && (0 != static_cast<node_type*>(m_pNode)->data)); } Self& operator++() { this->move<TreeIteratorBase::Rightward>(); return *this; } Self operator++(int) { Self tmp = *this; this->move<TreeIteratorBase::Rightward>(); return tmp; } Self& operator--() { this->move<TreeIteratorBase::Leftward>(); return *this; } Self operator--(int) { Self tmp = *this; this->move<TreeIteratorBase::Leftward>(); 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 DataType> class BinaryTreeBase : private Uncopyable { public: typedef Node<DataType> NodeType; protected: /// TreeImpl - TreeImpl records the root node and the number of nodes // // +---> Root(end) <---+ // | |left | // | begin | // | / \ | // | Left Right | // +---/ \-----+ // class TreeImpl : public NodeFactory<DataType> { typedef typename NodeFactory<DataType>::iterator iterator; typedef typename NodeFactory<DataType>::const_iterator const_iterator; public: NodeBase node; public: TreeImpl() : NodeFactory<DataType>() { 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(); } }; /** \class BinaryTree * \brief An abstract data type of binary tree. * * @see mcld::InputTree */ template<class DataType> class BinaryTree : public BinaryTreeBase<DataType> { 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<DataType> Self; typedef TreeIterator<value_type, NonConstTraits<value_type> > iterator; typedef TreeIterator<value_type, ConstTraits<value_type> > const_iterator; typedef PolicyIterator<value_type, NonConstTraits<value_type>, DFSIterator> dfs_iterator; typedef PolicyIterator<value_type, ConstTraits<value_type>, DFSIterator> const_dfs_iterator; typedef PolicyIterator<value_type, NonConstTraits<value_type>, BFSIterator> bfs_iterator; typedef PolicyIterator<value_type, ConstTraits<value_type>, BFSIterator> const_bfs_iterator; protected: typedef Node<value_type> node_type; public: // ----- constructors and destructor ----- // BinaryTree() : BinaryTreeBase<DataType>() { } ~BinaryTree() { } // ----- iterators ----- // bfs_iterator bfs_begin() { return bfs_iterator(BinaryTreeBase<DataType>::m_Root.node.left); } bfs_iterator bfs_end() { return bfs_iterator(BinaryTreeBase<DataType>::m_Root.node.right); } const_bfs_iterator bfs_begin() const { return const_bfs_iterator(BinaryTreeBase<DataType>::m_Root.node.left); } const_bfs_iterator bfs_end() const { return const_bfs_iterator(BinaryTreeBase<DataType>::m_Root.node.right); } dfs_iterator dfs_begin() { return dfs_iterator(BinaryTreeBase<DataType>::m_Root.node.left); } dfs_iterator dfs_end() { return dfs_iterator(BinaryTreeBase<DataType>::m_Root.node.right); } const_dfs_iterator dfs_begin() const { return const_dfs_iterator(BinaryTreeBase<DataType>::m_Root.node.left); } const_dfs_iterator dfs_end() const { return const_dfs_iterator(BinaryTreeBase<DataType>::m_Root.node.right); } iterator root() { return iterator(&(BinaryTreeBase<DataType>::m_Root.node)); } const_iterator root() const { return const_iterator(&(BinaryTreeBase<DataType>::m_Root.node)); } iterator begin() { return iterator(BinaryTreeBase<DataType>::m_Root.node.left); } iterator end() { return iterator(BinaryTreeBase<DataType>::m_Root.node.right); } const_iterator begin() const { return const_iterator(BinaryTreeBase<DataType>::m_Root.node.left); } const_iterator end() const { return const_iterator(BinaryTreeBase<DataType>::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<size_t DIRECT, class Pos> BinaryTree& join(Pos position, const DataType& value) { node_type *node = BinaryTreeBase<DataType>::createNode(); node->data = const_cast<DataType*>(&value); if (position.isRoot()) proxy::hook<TreeIteratorBase::Leftward>(position.m_pNode, const_cast<const node_type*>(node)); else proxy::hook<DIRECT>(position.m_pNode, const_cast<const node_type*>(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<size_t DIRECT, class Pos> BinaryTree& merge(Pos position, BinaryTree& pTree) { if (this == &pTree) return *this; if (!pTree.empty()) { proxy::hook<DIRECT>(position.m_pNode, const_cast<const NodeBase*>(pTree.m_Root.node.left)); BinaryTreeBase<DataType>::m_Root.summon( pTree.BinaryTreeBase<DataType>::m_Root); BinaryTreeBase<DataType>::m_Root.delegate(pTree.m_Root); pTree.m_Root.node.left = pTree.m_Root.node.right = &pTree.m_Root.node; } return *this; } }; } // namespace of mcld #endif