二叉树的一种C++实现

 

树是一种非线性的数据结构,最常用到的是树和二叉树,其中又以二叉树更为实用。

 

下面是二叉树的一个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__


 

你可能感兴趣的:(数据结构,C++,tree,null,Constructor,recursion)