树是一种非线性的数据结构,最常用到的是树和二叉树,其中又以二叉树更为实用。
下面是二叉树的一个C++实现:
/*btree.h*/ #ifndef __BINARY_TREE_H__ #define __BINARY_TREE_H__ #include <assert.h> #include <crtdbg.h> template<typename T> class BTNode { public: T data; BTNode<T> *parent; BTNode<T> *left; BTNode<T> *right; BTNode( T data = T(), BTNode<T> *parent = NULL, BTNode<T> *left = NULL, BTNode<T> *right = NULL ) : data(data), parent(parent), left(left), right(right) {} }; template<typename T> class BTree { public://constructors and copying controling functions BTree(BTNode<T> *initroot = NULL); BTree(const BTree<T>& other); virtual ~BTree(); BTree<T>& operator=(const BTree<T>& other); void Clone(const BTree<T>& other); void Attach(BTNode<T> *p);//node cannot be any node in this tree. void Destroy();// make empty public://utilizations T& GetNodeData(BTNode<T> *p); T GetNodeData(const BTNode<T> *p) const; void SetNodeData(BTNode<T> *p, const T &data); BTNode<T>*& GetRoot(); BTNode<T>* GetRoot() const; BTNode<T>*& GetParent(BTNode<T> *p); BTNode<T>* GetParent(const BTNode<T> *p) const; BTNode<T>*& GetLeftChild(BTNode<T> *p); BTNode<T>* GetLeftChild(const BTNode<T> *p) const; BTNode<T>*& GetRightChild(BTNode<T> *p); BTNode<T>* GetRightChild(const BTNode<T> *p) const; BTNode<T>*& GetLeftSibling(BTNode<T> *p); BTNode<T>* GetLeftSiblig(const BTNode<T> *p) const; BTNode<T>*& GetRightSibling(BTNode<T> *p); BTNode<T>* GetRightSibling(const BTNode<T> *p) const; int IsEmpty() const; public://public interfaces for core operation typedef void(* funtype)(const T&); void PreOrderTraverse(funtype Visit) const; void InOrderTraverse(funtype Visit) const; void PostOrderTraverse(funtype Visit) const; unsigned int GetNodesCount() const; // Get how many nodes unsigned int GetLeafCount() const; unsigned int GetDepth() const; private://private function implementing real core operations, like tranversion and recursion operations BTNode<T>* CloneSubTree(BTNode<T> *p);//clone(deeply copy) the subtree from the node pointet by p. void DestroySubTree(BTNode<T> *p); void PreOrderTraverse(const BTNode<T> *p,funtype Visit) const; void InOrderTraverse(const BTNode<T> *p,funtype Visit) const; void PostOrderTraverse(const BTNode<T> *p,funtype Visit) const; void GetNodesCount(const BTNode<T> *p, unsigned int *unCount) const; void GetLeafCount(const BTNode<T> *p, unsigned int *unCount) const; unsigned int GetDepth(const BTNode<T> *p) const; protected: BTNode<T> *m_pNodeRoot; }; /*------------------------------------------------------------------------ *constructor and copying controling functions ---------------------------------------------------------------------------*/ template<typename T> inline BTree<T>::BTree(BTNode<T> *initroot) : m_pNodeRoot(initroot) { } template<typename T> inline BTree<T>::BTree(const BTree<T>& other) : m_pNodeRoot(NULL) { if (NULL != other.m_pNodeRoot) m_pNodeRoot = CloneSubTree(other.m_pNodeRoot); } template<typename T> inline BTree<T>::~BTree() { Destroy(); } template<typename T> inline void BTree<T>::Attach(BTNode<T> *p) { ASSERT(p); if(m_pNodeRoot!=NULL) { Destroy(); } m_pNodeRoot = p; } template<typename T> inline BTree<T>& BTree<T>::operator=(const BTree<T> &p) { if(this==&p) { return *this; } if(m_pNodeRoot!=NULL) { Destroy(); } if (NULL != p.m_pNodeRoot) m_pNodeRoot = CloneSubTree(p.m_pNodeRoot); else m_pNodeRoot = NULL; return *this; } template<typename T> inline void BTree<T>::Clone(const BTree<T> &p) { /*if(this==&p) { return; } if(m_pNodeRoot!=NULL) { Destroy(); } if (NULL != p.m_pNodeRoot) m_pNodeRoot = CloneSubTree(p.m_pNodeRoot); else m_pNodeRoot = NULL;*/ operator=(p); } template<typename T> inline void BTree<T>::Destroy() { DestroySubTree(m_pNodeRoot); m_pNodeRoot = NULL; } /*------------------------------------------------------------------ *utilizations,e.g, gets and sets ---------------------------------------------------------------------*/ template<typename T> inline BTNode<T>*& BTree<T>::GetLeftChild(BTNode<T> *p) { ASSERT(p); return *(&(p->left)); } template<typename T> inline BTNode<T>* BTree<T>::GetLeftChild(const BTNode<T> *p) const { ASSERT(p); return p->left; } template<typename T> inline BTNode<T>*& BTree<T>::GetRightChild(BTNode<T> *p) { ASSERT(p); return *(&(p->right)); } template<typename T> inline BTNode<T>* BTree<T>::GetRightChild(const BTNode<T> *p) const { ASSERT(p); return p->right; } template<typename T> inline BTNode<T>*& BTree<T>::GetLeftSibling(BTNode<T> *p) { ASSERT(p); if (p->parent) return *(&(p->parent->left)); else return *(&(p->parent)); // return NULL; } template<typename T> inline BTNode<T>* BTree<T>::GetLeftSiblig(const BTNode<T> *p) const { ASSERT(p); if (p->parent) return p->parent->left; else return p->parent; // return NULL; } template<typename T> inline BTNode<T>*& BTree<T>::GetRightSibling(BTNode<T> *p) { ASSERT(p); if (p->parent) return *(&(p->parent->right)); else return *(&(p->parent)); // return NULL; } template<typename T> inline BTNode<T>* BTree<T>::GetRightSibling(const BTNode<T> *p) const { ASSERT(p); if (p->parent) return p->parent->right; else return p->parent; // return NULL; } template<typename T> inline BTNode<T>*& BTree<T>::GetParent(BTNode<T> *p) { ASSERT(p); return *(&(p->parent)); } template<typename T> inline BTNode<T>* BTree<T>::GetParent(const BTNode<T> *p) const { ASSERT(p); return p->parent; } template<typename T> inline T& BTree<T>::GetNodeData(BTNode<T> *p) { ASSERT(p); return p->data; } template<typename T> inline T BTree<T>::GetNodeData(const BTNode<T> *p) const { ASSERT(p); return p->data; } template<typename T> inline void BTree<T>::SetNodeData(BTNode<T> *p, const T &data) { ASSERT(p); p->data = data; } template<typename T> inline int BTree<T>::IsEmpty() const { return NULL == m_pNodeRoot; } template<typename T> inline BTNode<T>*& BTree<T>::GetRoot() { return *(&(m_pNodeRoot)); } template<typename T> inline BTNode<T>* BTree<T>::GetRoot() const { return m_pNodeRoot; } /*--------------------------------------------------------------------- *public interfaces for core operations ------------------------------------------------------------------------*/ template<typename T> inline void BTree<T>::PreOrderTraverse(funtype Visit) const { PreOrderTraverse(m_pNodeRoot, Visit); } template<typename T> inline void BTree<T>::InOrderTraverse(funtype Visit) const { InOrderTraverse(m_pNodeRoot, Visit); } template<typename T> inline void BTree<T>::PostOrderTraverse(funtype Visit) const { PostOrderTraverse(m_pNodeRoot, Visit); } template<typename T> inline unsigned int BTree<T>::GetNodesCount() const { unsigned int unCount; GetNodesCount(m_pNodeRoot, &unCount); return unCount; } template<typename T> inline unsigned int BTree<T>::GetLeafCount() const { unsigned int unCount = 0; GetLeafCount(m_pNodeRoot, &unCount); return unCount; } template<typename T> inline unsigned int BTree<T>::GetDepth() const { // Minus 1 here because I think the root node's depth should be 0. // So, don't do it if u think the root node's depth should be 1. return GetDepth(m_pNodeRoot) - 1; } /*------------------------------------------------------------------------------ *private functions: implementing recursion operations, tranversion operations and others. ---------------------------------------------------------------------------------*/ template<typename T> inline BTNode<T>* BTree<T>::CloneSubTree(BTNode<T> *p) { if (p) { BTNode<T> *pNewNode; try { pNewNode = new BTNode<T>; } catch(std::bad_alloc&) { return NULL; } pNewNode->data = p->data; pNewNode->parent = p->parent; pNewNode->left = CloneSubTree(p->left); pNewNode->right = CloneSubTree(p->right); return pNewNode; } else return NULL; } template<typename T> inline void BTree<T>::DestroySubTree(BTNode<T> *p) { if (p) { DestroySubTree(p->left); DestroySubTree(p->right); delete p; } } template<typename T> inline void BTree<T>::PreOrderTraverse(const BTNode<T> *p,funtype Visit) const { if (p) { Visit(p->data); PreOrderTraverse(p->left, Visit); PreOrderTraverse(p->right, Visit); } } template<typename T> inline void BTree<T>::InOrderTraverse(const BTNode<T> *p,funtype Visit) const { if (p) { InOrderTraverse(p->left, Visit); Visit(p->data); InOrderTraverse(p->right, Visit); } } template<typename T> inline void BTree<T>::PostOrderTraverse(const BTNode<T> *p,funtype Visit) const { if (p) { PostOrderTraverse(p->left, Visit); PostOrderTraverse(p->right, Visit); Visit(p->data); } } template<typename T> inline void BTree<T>::GetNodesCount( const BTNode<T> *p, unsigned int *unCount ) const { ASSERT(unCount); unsigned int unLeftCount; unsigned int unRightCount; if (NULL == p) *unCount = 0; else if ((NULL == p->left) && (NULL == p->right)) *unCount = 1; else { GetNodesCount(p->left, &unLeftCount); GetNodesCount(p->right, &unRightCount); *unCount = 1 + unLeftCount + unRightCount; } } template<typename T> inline void BTree<T>::GetLeafCount( const BTNode<T> *p, unsigned int *unCount ) const { ASSERT(unCount); if (p) { // if the node's left & right children are both NULL, it must be a leaf if ((NULL == p->left) && (NULL == p->right)) ++(*unCount); GetLeafCount(p->left, unCount); GetLeafCount(p->right, unCount); } } template<typename T> inline unsigned int BTree<T>::GetDepth(const BTNode<T> *p) const { unsigned int unDepthLeft; unsigned int unDepthRight; if (p) { unDepthLeft = GetDepth(p->left); unDepthRight = GetDepth(p->right); return 1 + // if don't plus 1 here, the tree's depth will be always 0 (unDepthLeft > unDepthRight ? unDepthLeft : unDepthRight); } else return 0; } #endif // __BINARY_TREE_H__