BST(二叉搜索树)AVL(高度平衡的二叉树)

#ifndef _BST_H
#define _BST_H
template<class Type>
class BST;
template<class Type>
class BSTNode
{
	friend BST<Type>;
public:
	BSTNode(Type x):data(x),LeftNode(NULL),RightNode(NULL){}
	BSTNode(Type value,BSTNode<Type>* left,BSTNode<Type>*right):data(value),LeftNode(left),RightNode(right){}
	~BSTNode()
	{}
private:
	Type data;
	BSTNode* LeftNode;
	BSTNode* RightNode;
};
template<class Type>
class BST
{
public:
	BST():root(NULL){}
	~BST()
	{}
public:
	bool Insert(Type &x)
	{
		return Insert(root,x);
	}
	bool Remove(Type x)
	{
	   return Remove(root,x);
	}
	Type Max()
	{
       return  Max(root);
	}
    BSTNode<Type>* Search(const Type& x)
	{
		return Search(root,x);
	}
	BSTNode<Type>* Parent(const Type &key)const
	{
		return Parent(root,x);
	}
protected:
	//非递归:
	bool Insert(BSTNode<Type> *&t,Type &x)
	{
		BSTNode<Type>* p = t;
		BSTNode<Type>* pr=NULL;
		while(p != NULL)
		{
		  if(x <p->data)
		  {
			  pr = p;
			  p = p->LeftNode;
		  }
		  else if(x > p->data)
		  {
			  pr = p;
			  p = p->RightNode;
		  }
		 else
			 return false;
		}
		p = new BSTNode<Type>(x);
		if(t ==NULL)
			t = p;
		else
		{
			if(x <pr->data)
				pr->LeftNode = p;
			else if(x > pr->data)
				pr->RightNode = p;
		 }
      }
   BSTNode<Type>* Search(BSTNode<Type>*& t,const Type &x)const
   {
	   BSTNode<Type>* p = t;
	   BSTNode<Type>* q =NULL;
	   if(t == NULL)
		   return NULL;
	   else
	   {
		   while(p !=NULL)
		   {
			   if(p->data == x)
				   return p;
				else if(x < p->data )
			       p=p->LeftNode ;
			    else
				   p= p->RightNode ;
		   }
		   if( p== NULL)
			   return NULL;
	   }
   }
	bool Rmove(BSTNode<Type> *t,Type x)
	{
      if(t == NULL)
		  return false;
	  while(t!=NULL)
	  {
        if(x <t->data )
			t=t->LeftNode;
		else if(x >t->data )
			t = t->RightNode ;
		else
		{
			if(t->LeftNode ==NULL && t->RightNode == NULL)
			{
				delete t;
				t= NULL;
				return true;
			}
			if(t->LeftNode != NUll && t->RightNode == NULL)
			{
				BSTNode<Type>* p =t;
				t =p->LeftNode;
				delete p;
				p =NULL;
			}
			if(t->LeftNode == NULL && t->RightNode !=NULL)
			{
				BSTNode<Type>* p= t;
				t= t->RightNode ;
				delete p;
				p= NULL;
			}
			if(t->LeftNode != NULL && t->RightNode != NULL)
			{
				BSTNode<Type>* p =t->RightNode ;
				while(p->LeftNode != NULL)
					p= p->LeftNode ;
				t->data = p->data ;
				remove(t->RightNode ,p->data );
			}
		}
	  }
	}
	Type Max(BSTNode<Type>* t)
	{
		if(t ==NULL)
			return 0;
		else
		{
			BSTNode<Type>* p =t;
			BSTNode<Type>*pr=NULL;
			while(p!=NULL)
			{
				pr =p;
				p =p->RightNode;
			}
			return pr->data ;
		}
	}
	BSTNode<Type>* Parent(BSTNode<Type>* t,Type& key)
	{
		if(t == NULL)
		{
			return NULL;
		}
		else
		{
			BSTNode<Type>* p = t;
			if(key < p->data )
				p = p->LeftNode ;
			else if(key > p->data )
				p=p->RightNode ;
			else
				return p;
		}
	}
private:
	BSTNode<Type>* root;
};
#endif

以上是二叉搜索树的实现代码。

可以这样子测试:

#include<iostream>
#include"bst.h"
using namespace std;
int main()
{
	int ar[] ={53,78,65,17,190,9,81,45,23};
	int n = sizeof(ar)/sizeof(int);	
	BST<int> bst;
	for(int i =0;i<n;++i)
	{
	
		bst.Insert(ar[i]);
	}
	//cout<<"Max="<<bst.Max();
	bst.Search(65);
	return 0;
}
/*
//递归:这里为什么没有返回根结点?因为传的是root的引用,所以就会直接改变root;
	/*bool Insert(BSTNode<Type> *&t,Type &x)
	{
		if(t==NULL)
		{
			t= new BSTNode<Type>(x);
			return true;
		}
		else
		{
			if(x <t->data)
				Insert(t->LeftNode,x);
			else if(x > t->data)
				Insert(t->RightNode,x);
			else
				return false;
		}
		

	}*/

AVL叫做高度平衡的二叉树,以前老记不住这个名字,现在懂了,AVL它是在BST(平衡的二叉树中衍生过来的),因为BST树可能会出现在高度上规则差距很大的树,毕竟他的规则只是比根结点大的作为根结点的右结点,比根结点小的作为根结点的左树;他在BST树的基础上又增加了一条规则,左右子树在高度上最大的高度差只能是1,所以叫他是高度上平衡的排序树;

以下是AVL树的实现:

 

#pragma once

#include<iostream>
#include<stack>
using namespace std;

template<class Type>
class AVL;

template<class Type>
class AVLNode
{
	friend class AVL<Type>;
public:
	AVLNode():data(Type()),leftChild(NULL),rightChild(NULL),bf(0)
	{}
	AVLNode(Type d,AVLNode<Type> *left=NULL,AVLNode<Type>*rigth=NULL)
		:data(d),leftChild(left),rightChild(rigth),bf(0)
	{}
	~AVLNode()
	{}
private:
	Type data;
	AVLNode *leftChild;
	AVLNode *rightChild;
	int bf;
};
template<class Type>
class AVL
{
public:
	AVL() : root(NULL)
	{}
	~AVL()
	{}
public:
	bool Insert(const Type &x)
	{
		return Insert(root, x);
	}
	bool Remove(const Type &x)
	{
		return Remove(root, x);
	}
protected:
	bool Insert(AVLNode<Type>*&t, const Type &x);
	void RotateR(AVLNode<Type> *&ptr);
	void RotateL(AVLNode<Type> *&ptr);
	void RotateRL(AVLNode<Type> *&ptr);
	void RotateLR(AVLNode<Type> *&ptr);
private:
	AVLNode<Type> *root;
};

 

 

(1)插入函数Insert函数:

 

 

template<class Type>
bool AVL<Type>::Insert(AVLNode<Type>*&t, const Type &x)
{
///
这一部分使用非递归的做法实现BST的插入;这里用到了栈,是因为你每次插入一个节点以后都要修改他的父结点的平衡因子,
并且修改第一个父节点的平衡因子之后再修改他的父父结点的平衡因子,用一个栈有利于记录这个结点插入的时候走过的路径,那么在回溯的时候也就方便了;
	stack<AVLNode<Type>*> st;
	AVLNode<Type> *p = t;
	AVLNode<Type> *pr = NULL;
	while(p != NULL)
	{
		if(x == p->data)
			return false;
		pr = p;
		st.push(pr);
		if(x < p->data)
			p = p->leftChild;
		else
			p = p->rightChild;
	}
	p = new AVLNode<Type>(x);
	if(pr == NULL)//这是刚插入根结点的情况;
	{
		t = p;
		return true;
	}
	if(x < pr->data)
		pr->leftChild = p;
	else
		pr->rightChild = p;
到此位置,新插入的结点已经与之前的结点建立了联系,插入到他该插入的地方;接下来就要看新结点的插入对他的父节点的平衡因子有何影响;

///
	while(!st.empty())
	{
		pr = st.top();
		st.pop();
		if(p == pr->leftChild)
			pr->bf--;
		else
			pr->bf++;
		if(pr->bf == 0)
			break;
		if(pr->bf==-1 || pr->bf==1)//倒回去继续查看父结点的平很因子;
		{
			p = pr;
		}
		else
		{
                 ///到这一步那肯定就不平衡了,需要调整平衡因子
			if(pr->bf < 0)
			{
				if(p->bf < 0)
				{
					cout<<"RotateR"<<endl;
					RotateR(pr);
					
				}
				else 
				{
					cout<<"RotateLR(pr)"<<endl;
					RotateLR(pr);
					
				}
			}
			else
			{
				if(p->bf > 0)  
				{
					cout<<"RotateL"<<endl;
				RotateL(pr);
					
				}
				else           
				{
					cout<<"RotateRL"<<endl;
					RotateRL(pr);
				}
			}
			break;//调整完以后一定要直接break;
		}
	}
到此位置,不平衡的结点已经调整过来了,但是以root为根结点的二插树的内部已经发生了变换,所以下面就是要将修改好的而插入与他的之前的父节点建立连接;
///
	//目的是把调整过了平衡因子的结点和之前的结点关联起来;
	if(st.empty())
	{
		//如果栈空了,说明他就是根结点
		t = pr;
	}
	else
	{
		//否则把栈顶元素弹出来,将其连接起来;
		AVLNode<Type> *q = st.top();//它是原来的父节点
		if(pr->data < q->data)
			q->leftChild = pr;
		else
			q->rightChild = pr;

	}
	return true;
}

 

旋转函数的我觉得简单的方法就是把旋转后的结果写出来,然后在将原来的结点做出相应的调整,并且一定要记得调整平衡因子;

 

template<class Type>
void AVL<Type>::RotateR(AVLNode<Type> *&ptr)
{
	AVLNode<Type> *subR = ptr;
	ptr = ptr->leftChild;
	//ptr->rightChild = sub->leftChild ;//造成sub的leftChild有俩个了;
	subR->leftChild = ptr->rightChild;
	ptr->rightChild = subR;
	ptr->bf = subR->bf = 0;
}

template<class Type>
void AVL<Type>::RotateL(AVLNode<Type> *&ptr)
{
	AVLNode<Type> *subL = ptr;
	ptr = ptr->rightChild;
	subL->rightChild = ptr->leftChild;
	ptr->leftChild = subL;
	ptr->bf = subL->bf = 0;
}
template<class Type>
void AVL<Type>::RotateLR(AVLNode<Type> *&ptr)
{
	AVLNode<Type> *subL = ptr->leftChild;
	AVLNode<Type> *subR = ptr;	ptr = subL->rightChild;
	subL->rightChild = ptr->leftChild;
	ptr->leftChild = subL;
	// ptr的平衡因子没有改
	if(ptr->bf <= 0)
		subL->bf = 0;
	else
		subL->bf = -1;

	subR->leftChild = ptr->rightChild;
	ptr->rightChild = subR;

	if(ptr->bf == -1)
		subR->bf = 1;
	else
		subR->bf = 0;
	ptr->bf = 0;
}
template<class Type>//一定是从当前不平衡结点初开始旋转;
void AVL<Type>::RotateRL(AVLNode<Type> *&ptr)
{
	AVLNode<Type> * subL = ptr;//ptr最终会成为左结点;
	AVLNode<Type> * subR = ptr->rightChild ;//它会成为右节点;
	ptr = subR->leftChild ;//最终的头结点
	//以下是安排最终的左结点和最终的更结点之间附属结点之间的变化;画图更易理解
	subL->rightChild = ptr->leftChild ;
	ptr->leftChild = subL;
	if(ptr->bf <= 0)
	{
		subL->bf = 0;
	}
	else
	{
		subL->bf = -1;
	}
	//以下安排最终的右结点和根结点他们的附属结点直接的变化,画图更易理解
	subR->leftChild = ptr->rightChild ;
	ptr->rightChild = subR;
	if(ptr->bf <=0)
	{
		subR->bf = -1;//有问题;
	}
	else
	{
		subR->bf = 0;
	}
	ptr->bf = 0;
}

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值