AVL树的基本旋转和调平

                                          AVL树的基本旋转和调平

   概念:什么是AVL树,简单的来说,就是一颗排序并且是高度平衡的一棵二叉树。

   那么二叉树是怎么做到的呢?肯定是不断的插入不断调节。

   结构:

        struct AVLNode
	{
		AVLNode *parent;
		AVLNode *leftchild;
		AVLNode *rightchild;
		int    balance;//平衡因子
		KeyType key;
	};
     简单的举个例子:

     简单的旋转:

     1.在一条直线上的简单旋转

     2.多了几个分支的旋转


  以上的旋转基本都是在一条直线上的旋转,只要旋转一次就可以将树调节平衡。但是我们平时遇到的多情况下都是不在一条直线上的旋转,那么这就是很常见的多双旋转

    下面就是简单的图例:(调左平衡的时候,假设右边已经平衡)

      在一条直线上的时候的旋转。

分别加在F,G处。就不再是直线了,就是一条折线

     


  代码:

#include<iostream>
using namespace std;

//C++版

template <typename KeyType>
class AVLTree
{
private:
	struct AVLNode
	{
		AVLNode *parent;
		AVLNode *leftchild;
		AVLNode *rightchild;
		int    balance;
		KeyType key;
	};
	AVLNode *root;
	static AVLNode *BuyNode()
	{
		AVLNode *p = new AVLNode;
		memset(p,0,sizeof(p));
		return p;
	}
	static void freeNode(AVLNode *p)
	{
		delete p;
	}
	static AVLNode *First(AVLNode *p)
	{
		if(p == NULL) return p;
		while(p!= NULL && p->leftchild != NULL)
			p = p->leftchild;
		return p;
	}
	static AVLNode *Next(AVLNode*p)
	{
		if(p == NULL) return p;
		AVLNode *s = p->parent;
		if(p->rightchild != NULL)
		{
			return First(p->rightchild);
		}
		else
		{
			//如果是右孩子
			while(s != NULL && s->leftchild != p)//不是左孩子,那就是右孩子
			{
				p = s;
				s = s->parent;
			}
			return s;
		}

	}
	static bool insert(AVLNode *&ptr,const KeyType kx,AVLNode *pa)
	{
		bool res = false;
		if(ptr == NULL)
		{
			ptr = BuyNode();
			ptr->key = kx;
			ptr->parent = pa;
			ptr->balance = 0;
			ptr->leftchild = NULL;
			ptr->rightchild = NULL;
			res = true;
		}
		else
		{   
			if(ptr->key >kx)
			{
				res = insert(ptr->leftchild,kx,ptr);
				switch(ptr->balance)
				{
				case 0:
					ptr->balance = -1;
					break;
				case 1:
					ptr->balance = 0;
					break;
				case -1:
					ptr->balance = -2;
					LeftBalance(ptr);
					break;
				}
			}
			else if(ptr->key < kx)
			{
				res = insert(ptr->rightchild,kx,ptr);
				switch(ptr->balance)
				{
				case 0:
					ptr->balance = 1;
					break;
				case -1:
					ptr->balance = 0;
					break;
				case 1:
					ptr->balance = 2;
					RightBalance(ptr);
					break;
				}
			}
		}
		return res;
	}
	static void Midinder(AVLNode *p)
	{ 
		if(p == NULL) return ;
		for(AVLNode *s = First(p);s != NULL;s = Next(s))
		{
			cout<<s->key<<" ";
		}
		cout<<endl;
	}
	static bool ReMove(AVLNode *&ptr,const KeyType kx)
	{
		bool res = false;
        if(ptr == NULL)  return res;
		if(ptr->key > kx)
		{
			res = ReMove(ptr->leftchild,kx);
		}
		else if(ptr->key < kx)
		{
			res = ReMove(ptr->rightchild,kx);
		}
		else if(ptr->leftchild != NULL && ptr->rightchild != NULL) //删除双分支(狸猫换太子)
		{
			AVLNode *s = Next(ptr);
			ptr->key = s->key;
			res = ReMove(ptr->rightchild,s->key);
		}
		else//删除单分支  叶子结点   根
		{
			AVLNode *child = ptr->leftchild != NULL ? ptr->leftchild : ptr->rightchild;
			AVLNode *pa = ptr->parent;
			if(child != NULL)
				child->parent = pa;
			/*if(pa->leftchild == ptr)
			{
				pa->leftchild = child;
			}
			else if(pa->rightchild == ptr)
			{
				pa->rightchild = child;
			}*/
			freeNode(ptr);
			ptr = child;
			res = true;
		}

		return res;
	} 
	//AVL树的左旋和右旋
	//右旋
	static void RotateRigth(AVLNode *&ptr)
	{

		if(ptr == NULL) return ;
		AVLNode *p = ptr->leftchild;
		p->parent = ptr->parent;
		ptr->leftchild = p->rightchild;
		if(p->rightchild != NULL)
		{
			p->rightchild->parent = ptr;
		}
		p->rightchild = ptr;
		ptr->parent = p;
		ptr = p;

	}
	//右旋
	static void RotateLeft(AVLNode *& ptr)
	{
		AVLNode *p = ptr->rightchild;
		p->parent = ptr->parent;
		ptr->rightchild = p->leftchild;
		if(p->leftchild != NULL)
		{
			p->leftchild->parent = ptr;
		}
		p->leftchild = ptr;
		ptr->parent = p;
		ptr = p;
	}
	//右边调平衡 (假设右边已经平和衡了)
	static void LeftBalance(AVLNode *&ptr)
	{
		if(ptr == NULL) return ;
		AVLNode *leftsub = ptr->leftchild,*rightsub = NULL;
		switch(leftsub->balance)
		{
		case 0:
			cout<<"left is already balance"<<endl; break;
		case -1:
			ptr->balance = 0;
			leftsub->balance = 0;
			RotateRigth(ptr);
			break;
		case 1:
			rightsub = leftsub->rightchild;
			switch(rightsub->balance)
			{
			case 0:
				ptr->balance = 0;
				leftsub->balance = 0;
				break;
			case 1://加在G的位置
			     ptr->balance = 0;
				 leftsub->balance = -1;
				 break;
				 
			case -1://加在F的位置
				ptr->balance = 1;
				leftsub->balance = 0;
				break;
			}
			rightsub->balance = 0;
			RotateLeft(ptr->leftchild);
			RotateRigth(ptr);
			break;
		}
	}
	//右边调平
	static void RightBalance(AVLNode *&ptr)
	{
		if(ptr == NULL) return ;
		AVLNode *rightsub  = ptr->rightchild,*leftsub = NULL;
		switch(rightsub->balance)
		{
		case 0:
			cout<<"right already balance"<<endl;
			break;
		case 1:
			ptr->balance = 0;
			rightsub->balance = 0;
			RotateLeft(ptr);
			break;
		case -1:
			leftsub = rightsub->leftchild;
			switch(leftsub->balance)
			{
			case 0:
				ptr->balance = 0;
                rightsub->balance = 0;
				break;
			case 1:
				ptr->balance = -1;
				rightsub->balance = 0;
				break;
			case -1:
				ptr->balance = 0;
                rightsub->balance = -1;
				break;
			}
			RotateRigth(ptr->rightchild);
			RotateLeft(ptr);
			break;
		}
	}
public:
	AVLTree():root(NULL){}
	~AVLTree(){}
	//C++ 插入节点
	bool insert(const KeyType kx)
	{
		return insert(root,kx,NULL);
	}
	void Midinder()const
	{
		return Midinder(root);
	}
	//C++删除节点
	bool  ReMove(const KeyType kx)
	{
          return ReMove(root,kx);
	}
};

int main()
{
	AVLTree<int> mytree;
	//int  str[] = {53,17,78,9,45,65,87,24,81,97,89,53,87};
	int str[] = {24,17,9};
	int len = sizeof(str)/sizeof(str[0]);

	for(int i = 0;i < len;++i)
	{
		mytree.insert(str[i]);
	}
	cout<<endl;
	mytree.Midinder();
	//int i = 0;
	//while(cin>>i,i != -1)
	//{
	//	//s = search(root,i);
	//	mytree.ReMove(i);
	//	mytree.Midinder();
	//}
   
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值