二叉查找树的C++实现

二叉查找树的插入和删除详解请看http://blog.csdn.net/sysu_arui/article/details/7865864

前面详细讲解了二叉查找树插入和删除,现在给出完整的C++实现,代码如下:

#include <cstdlib>
#include <iostream>

using namespace std;

template <typename T>
class BinarySearchTree
{
	public:
		BinarySearchTree() : root(NULL){}
		BinarySearchTree(const BinarySearchTree& rhs) : root(NULL)
		{
			*this = rhs;
		}
		~BinarySearchTree()
		{
			makeEmpty();
		}
	
		//返回最大的元素值 
		const T& findMax()const
		{
			if(!isEmpty())
			{
				return findMax(root)->element;
			}
		}
		//返回最小的元素值 
		const T& findMin()const
		{
			if(!isEmpty())
			{
				return findMin(root)->element;
			}
		}
		//判断是否包含给定元素
		bool contains(const T& x)const
		{
			return contains(root,x);
		}
		//判断二叉查找树是否为空 
		bool isEmpty()const
		{
			return root == NULL;
		}
		//中序输出二叉查找树 
		void printTree(ostream& out = cout)const
		{
			if(isEmpty())
			{
				out<<"Empty Tree"<<endl;
			}
			else
				printTree(root,out);
		}	


		//把二叉查找树置空	
		void makeEmpty()
		{
			makeEmpty(root);
		}
		//插入给定元素 
		void insert(const T& x)
		{
			insert(root,x);
		}
		//删除给定元素 
		void remove(const T& x)
		{
			remove(root,x);			
		}
		//重载赋值运算符 
		const BinarySearchTree & operator=(const BinarySearchTree &rhs)
		{
			if(this != &rhs)
			{
				makeEmpty();
				root = clone(rhs.root);
			}
			return *this;
		}
		
		
	private:
		struct BinaryNode
		{
			T element;
			BinaryNode * left;
			BinaryNode * right;
			
			BinaryNode(const T& elem, BinaryNode* lt=NULL, BinaryNode *rt=NULL)
			:element(elem),left(lt),right(rt){}
		};
		
		BinaryNode *root;		//根结点 
		
		//在以t为根结点的树中,插入元素x 
		void insert(BinaryNode* & t , const T& x)
		{
			if( t == NULL )
            	t = new BinaryNode( x, NULL, NULL );
	        else if(x < t->element)
	            insert(t->left,x);
	        else if(t->element < x)
	            insert(t->right,x);
	        else
	            ;  // 重复元素,不插入 
		}
		//在以t为根结点的树中,删除元素x 
		void remove(BinaryNode* & t , const T& x)
		{
			if(t == NULL)
            	return;   
	        if(x < t->element)
	            remove(t->left,x);
	        else if(t->element < x)
	            remove(t->right,x);
	        else if(t->left && t->right) // 左右子女都存在 
	        {
	            t->element = findMin(t->right)->element;//后继 
	            remove(t->right,t->element);
	        }
	        else
	        {
	            BinaryNode *oldNode = t;
	            t = (t->left) ? t->left : t->right;
	            delete oldNode;
	        }
		}
//		//递归查找最小结点 
//		BinaryNode * findMin(BinaryNode *t)const
//		{
//			if(t==NULL)
//				return NULL;
//			if(t->left==NULL)
//				return t;
//			return findMin(t->left);
//		}
		//非递归查找最小结点
		BinaryNode * findMin(BinaryNode *t)const
		{
			if(t)
			{
				while(t->left)
				{
					t = t->left;
				}
			}
			return t;
		}

//		//递归查找最大结点
//		BinaryNode * findMax(BinaryNode *t)const
//		{
//			if(t==NULL || t->right==NULL)
//				return t;
//			return findMax(t->right);
//		}

		//非递归查找最大结点 
		BinaryNode * findMax(BinaryNode *t)const
		{
			if(t)
			{
				while(t->right)
				{
					t = t->right;
				}
			}
			return t;
		}
		
//		//递归查找是否包含给定元素 
//		bool contains(BinaryNode *t, const T& x)const
//		{
//			if(t)
//			{
//				if(x < t->element)
//					return contains(t->left,x);
//				else if(t->elment < x)
//					return contains(t->right,x);
//				else 
//					return true;
//			}
//			return false;
//		}
		//非递归查找是否包含给定元素  
		bool contains(BinaryNode *t, const T& x)const
		{
			while(t)
			{
				if(x < t->element)
					t = t->left;
				else if(t->element < x)
					t = t->right;
				else return true;
			}
			return false;
		}
		//中序遍历-递归 
		void printTree(BinaryNode* t, ostream& out)const
		{
			if(t)
			{
				printTree(t->left,out);
				out<<t->element<<" ";
				printTree(t->right,out);
			}
		}
		//删除二叉查找树 
		void makeEmpty(BinaryNode* & t)
		{
			if(t)
			{
				makeEmpty(t->left);
				makeEmpty(t->right);
				delete t;
				t = NULL;
			}
		}
		//复制二叉查找树 
		BinaryNode * clone(const BinaryNode* &t)const
		{
			if(t==NULL)
				return NULL;
			return new BinaryNode(t->element,clone(t->left),clone(t->right));
		}		 
};


int main(int argc, char *argv[])
{
	BinarySearchTree<int> bst;
	int x;
	
	while(cin>>x && x)//以0作为输入结束 
	{
		bst.insert(x);
	}
	
	cout<<"After insert:"<<endl;
	bst.printTree();
	cout<<endl<<"Min: "<<bst.findMin()<<endl;
	cout<<"Max: "<<bst.findMax()<<endl<<endl;
	
	cout<<"input the elements you want to remove:"<<endl;
	while(cin>>x && x)
	{
		bst.remove(x);	
	}
	
	cout<<"After remove :"<<endl;
	bst.printTree();
	cout<<endl<<endl;
	
	cout<<"After clear :"<<endl;
	bst.makeEmpty();
	bst.printTree();
	cout<<endl;
	
    system("PAUSE");
    return EXIT_SUCCESS;
}

注:

(1)该类为一个模板类,结点元素数据域类型可以是基本数据类型,也可以是复杂类对象。当使用复杂类对象时,类必须重载了赋值运算符和比较运算符,在上面的代码中,只用到了<比较运算符,所以类比较运算符至少得重载<。

(2)上面的成员函数有些同时给出了递归实现和非递归实现,有的只给出了递归实现,递归的好处是逻辑清晰,代码简洁,但是效率低下。其实弄清楚了原理,递归和非递归之间转换就很简单了。

(3)对于在一个含有n个元素的序列中查找给定元素的问题,如果采用简单的顺序查找,复杂度为O(n)。采用二叉查找树进行查找,如果树高为h,则复杂度为O(h)。对于含n个结点的二叉树,树的平均高度为h=「log(n+1)|。但是当给定的序列基本有序时,树的高度h接近n,此时时间复杂度几乎为O(n)。如当输入为递增序列时,查找树为一棵没有左子树的单支树,树高为n。为了尽可能的降低树的高度,减少检索次数,我们可以把输入序列进行随机化,构造一棵随机化的二叉查找树。或则采用其他的平衡查找树,如红黑树,AVL树等,后面会一一讲解。

二叉查找树的插入和删除详解请看:http://blog.csdn.net/sysu_arui/article/details/7865864

参考资料:

Data Structures and Algorithm Analysis in C++(third editon) (数据结构与算法分析C++描述,第3版 )

    原文作者:二叉查找树
    原文地址: https://blog.csdn.net/sysu_arui/article/details/7892593
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞