二叉查找樹的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版 )

發佈了38 篇原創文章 · 獲贊 10 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章