数据结构之二叉查找树的C++实现

     二叉树是结构最简单的树了,而二叉查找树又是特殊的二叉树,它能实现高效的查找,删除,插入等基本操作,STL里的map与set就是用了自平衡的二叉查找树的思想实现的

不过我这里先不实现自平衡功能,但这又是很重要的,等下我会说明,现在还是先看看二叉查找树的实现:


 首先是Btree头文件:

  

#ifndef BTREE_H
#define BTREE_H
#include<iostream>
using namespace std;
template <class Comparable>  //必须是可比较大小的数据类型
class Btree
{
	public:

		Btree(){root=NULL;}
		Btree(const Btree &rhs)
		{
		root=NULL;
		*this=rhs;
		}
		~Btree()
		{
           	makeEmpty();
		}
		const Comparable & findMin()const
		{
			return findMin(root)->element;
		}
        const Comparable & findMax()const
		{
			return findMax(root)->element;
		};
		bool contains(const Comparable &x)const//查找;
		{
			return contains(x,root);
		}

		bool isEmpty()const
		{
			return root==NULL;
		}
		void printTree()
		{
			printTree(root);
		}
		void display()
		{
		    display(root);
		}
		void makeEmpty()
		{
			makeEmpty(root);
		}
		void insert(const Comparable &x)
		{
			insert(x,root);
		}
        void remove( Comparable &x)
		{
			remove(x,root);
		}
		const Btree & operator=(const Btree &rhs)
		{
			if(this!=&rhs)
			{
				makeEmpty();
				root=clone(rhs.root);
			}
			return *this;
		};
		friend	ostream & operator <<(ostream &out,Btree<Comparable> &T)
		{
	         T.printTree();
             return out;
          }
		Btree & operator -(Btree &T)
		{
		  while(!T.isEmpty())
		  {
		     this->remove(T.root->element);
		     T.remove(T.root->element);
         }
		   return *this;
		}
	private:
		struct BNode
		{
			Comparable element;
			BNode *left;
			BNode *right;
			BNode(const Comparable &ele,BNode *lt=NULL,BNode *rt=NULL)
				:element(ele),left(lt),right(rt){}
		};
		BNode *root;

		void insert(const Comparable &x,BNode *&T)const
		{
			if(T==NULL)
				T=new BNode(x);
			BNode *t=T,*tt=NULL;      //非递归实现

			while(t!=NULL)
			{
				tt=t;
				if(x<t->element)
					t=t->left;
				else if(t->element<x)
					t=t->right;
                else
                return;
			}
			t=new BNode(x);
			if(tt->element>x)
				tt->left=t;
			else
				tt->right=t;


				/*else if(x<=t->element)  //递归实现
				insert(x,t->left);
				else if(x>t->element)
				insert(x,t->right);

			*/
		}
        void remove(Comparable &x,BNode * &T)const
		{
			if(T==NULL)
	              	return ;
			BNode *t=T,*tt=NULL;           //非递归实现
			while(t!=NULL)
			{

				if(x<t->element)
				{tt=t;t=t->left;}
				else if(x>t->element)
				{tt=t;	t=t->right;}
				else if(t->left !=NULL && t->right !=NULL)
				{
					x=t->element=findMin(t->right)->element;
					tt=t;
                    t=t->right;
				}
			/*if(x<t->element)           //递归实现
			{
				remove(x,t->left);
			}
			else if(x>t->element)
			{
				remove(x,t->right);
			}
			else if(t->left !=NULL && t->right !=NULL)
			{
				t->element=findMin(t->right)->element;
				remove(t->element,t->right);
			}*/
			else
			{
				BNode *oldnode=t;
				t=(t->left!=NULL)?t->left:t->right;
				delete oldnode;
				break;
			}
			}
			if(tt==NULL)
			{
				T=t;
				return;

			}

		    else if(tt->element>x)
				tt->left=t;
			else
				tt->right=t;


		}
		BNode *findMin(BNode *t)const
		{
			if(t==NULL)
				return NULL;
			if(t->left==NULL)
				return t;
	           return findMin(t->left);
		}
		BNode *findMax(BNode *t)const
		{
			if(t==NULL)
				return NULL;
			if(t->right==NULL)
				return t;
	           return findMax(t->right);
		}
		bool contains(const Comparable &x,BNode *t)const//查找;
		{
			if(t==NULL)
				return false;
			else if(x<t->element)
				return contains(x,t->left);
			else if(x>t->element)
				return contains(x,t->right);
			else
				return true;
		}

		void makeEmpty(BNode * &t)
		{
			if(t!=NULL)
			{
				makeEmpty(t->left);
				makeEmpty(t->right);
				delete t;
			}
			t=NULL;
		}
		void printTree(BNode * t)const
		{
           	if(t!=NULL)
			{
				printTree(t->left);
				cout<<t->element<<" ";
				printTree(t->right);
			}
		}

      void display(BNode * t,int n=0)const
		{
           	if(t!=NULL)
			{
				display(t->left,n+1);
				for(int i=1;i<=n;i++)
				cout<<"   ";
				cout<<t->element<<endl;
				display(t->right,n+1);
			}
		}
		BNode *clone(BNode *t)const
		{
			if(t==NULL)
				return NULL;
			return new BNode(t->element,clone(t->left),clone(t->right));
		}
};

#endif
可以看到,唯一的难点在于插入和删除,其实如果用递归实现的话,还是很简单,但节点一多就可能会出现栈溢出的可能,而且递归效率原本就没有循环的效率高。

然后是测试代码:


#include"Btree.h"
#include<cstdlib>
#include<ctime>
#include<cstdio>
int main(){
  freopen("out.txt","w",stdout);
  Btree<int> b;
  srand(time(NULL));
   int n;
   cin>>n;
   clock_t start,finish;
   start=clock();
   for(int i=0;i<n;i++)
   {
	    b.insert(rand()%n);
   }
   finish=clock();
   cout<<double(finish-start)/CLOCKS_PER_SEC <<"s"<<endl;
   b.printTree();
   b.display();
   Btree<int> t(b);
   cout<<endl;
   for(int i=0;i<=n/2;i++)
	   t.remove(i);
   cout<<t<<endl;
   return 0;
   fclose(stdout);
}

输入100后的结果如下:



0.000104s
1 2 4 5 6 7 8 9 10 11 13 14 15 18 21 23 24 25 27 30 33 34 36 38 39 41 43 46 48 51 54 56 57 58 59 60 62 63 64 66 67 68 70 71 74 75 76 77 78 79 80 81 83 84 85 86 87 88 89 90 91 92 93 96 99             1
         2
               4
            5
               6
      7
                  8
               9
            10
                  11
               13
                  14
                        15
                     18
         21
                  23
               24
                        25
                     27
                              30
                           33
                        34
                              36
                                 38
                                    39
                           41
                                 43
                                       46
                                    48
                              51
                  54
                     56
                        57
            58
                     59
                  60
                              62
                           63
                        64
                     66
                           67
                              68
                        70
                           71
               74
                        75
                     76
                              77
                           78
                                 79
                              80
                        81
                  83
                     84
   85
      86
87
      88
         89
   90
      91
            92
         93
            96
               99


51 54 56 57 58 59 60 62 63 64 66 67 68 70 71 74 75 76 77 78 79 80 81 83 84 85 86 87 88 89 90 91 92 93 96 99 

中间输出的是树的大致样子,现在就可以来讲讲为什么自平衡那么重要了,假设我们是按照数的大小顺序来插入的话如从1插到100,那么树就有100层,这时无论做什么操作,都相当与链表,开销很大,都是O(n)的,所以我们一定要想办法让二叉查找树具有自平衡的功能!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值