平衡二叉树

#pragma once

#define VOID template<class T>\
void AVItree<T>::

#define NODE template<class T>\
typename AVItree<T>::node* AVItree<T>::

#define max(a,b) (a)>(b)?(a):(b)
#define tempRoot (*t)

//平衡二叉树
template <class T>
class AVItree
{
	struct node
	{
		T data;
		node *left, *right;
		int height;//树的高度、平衡因子
		node(const T data) :data(data) { left = right = NULL; height = 0; }
	}*root;

public:
	AVItree() { root = NULL; }
	~AVItree() { _clear(&root); }
	//插入数据
	void insert(T data) { _ins(&root, data); }
	//中序遍历输出
	void midOut() { _midP(&root); }
	//获取树的高度
	int getHG() { return getHeight(&root); }
	//删除节点
	void del(T data) { _del(data, &root); }
private:
	node* findMax(node**);//得到数据最大的结点
	node* findMin(node**); 
	
	node* Lrotate(node**);//旋转
	node* Rrotate(node**);
	node* LRrotate(node**);
	node* RLrotate(node**);

	int getHeight(node**);//得到树的高度
	void _ins(node**, T);//插入
	void _midP(node**);//中序输出
	void _clear(node**);//清空
	void _del(T const, node**);//删除节点
};

//删除指定节点
VOID _del(T const data, node*tempRoot)
{
	if (!tempRoot)
		return;//我都不是树,你删除个屁呀
	else if (data == tempRoot->data)
	{//找到了,该死的数藏在这里了
		if (tempRoot->left && tempRoot->right)
		{//他娘的左右子树都不是空树,让老子心烦
			if (getHeight(&tempRoot->left) > getHeight(&tempRoot->right))
			{//左树看上去比较高大,砍他
				tempRoot->data = findMax(&tempRoot->left)->data;
				//把左树上那个最大叶子给我拿意大利炮轰了
				_del(tempRoot->data, &tempRoot->left);
			}
			else
			{//NO NO NO 右子树看着更让人生气
				tempRoot->data = findMin(&tempRoot->right)->data;
				//那就让右树上最小的叶子切腹自尽
				_del(tempRoot->data,&tempRoot->right);
			}
		}
		else  
		{//左右子树有至少一个是空的
			node *old = tempRoot;
			if (tempRoot->left || tempRoot->right)
			{
				tempRoot = tempRoot->left ? tempRoot->left : tempRoot->right;
				delete old;
			}
			else
			{
				delete tempRoot;
				tempRoot = NULL;
			}

		}//因为是平衡树,且只有一个节点,那就肯定已经是末端了,不要多想了
	}
	else if (data < tempRoot->data)
	{//没找到,但是比我小,给我去左边搜
		_del(data, &tempRoot->left);
		if (getHeight(&tempRoot->right)	- getHeight(&tempRoot->left) > 1)
		{
			//还能平衡吗?因为是删的左边,
//左边已经不可能会比右边还粗大了,好汉不提当年勇,快平衡一下吧
			if (getHeight(&tempRoot->right->left) >	getHeight(&tempRoot->right->right))
				//左边不能比右边大,看我乾坤大挪移
				tempRoot = LRrotate(&tempRoot);
			else//不平衡,总要移动一下嘛
				tempRoot = Rrotate(&tempRoot);
		}
		else//心理上还能承受这次打击,只调整下高度就好了
			tempRoot->height = max(getHeight(&tempRoot->left),getHeight(&tempRoot->right)) + 1;
		//注意这里不是-1哦,毕竟,爸爸总要比孩子高一辈嘛
	}
	else//没找到,再去右边找找
	{
		_del(data, &tempRoot->right);
		if (getHeight(&tempRoot->left) - getHeight(&tempRoot->right) > 1)
		{
			if (getHeight(&tempRoot->left->right) >	getHeight(&tempRoot->left->left))
				tempRoot = RLrotate(&tempRoot);
			else
				tempRoot = Rrotate(&tempRoot);
		}
		else
			tempRoot->height = max(getHeight(&tempRoot->left),getHeight(&tempRoot->right)) + 1;
	}
//在找不到就说明这个傻逼用户想要删一个不存在的数,不管他了	
}
//求树的高度
template<class T>
int AVItree<T>::getHeight(node*tempRoot)
{
	if (!tempRoot)
		return -1;
	else 
		return tempRoot->height;
}
//右旋转
NODE Rrotate(node *tempRoot)
{
	node *q = tempRoot->left;
	tempRoot->left = q->right;
	q->right = tempRoot;
	tempRoot = q;
	//旋转完毕,下面是高度的重新调整
    tempRoot->height = max(getHeight(&tempRoot->left),
		getHeight(&tempRoot->right)) + 1;

    q->height = max(getHeight(&q->left),
		getHeight(&q->right)) + 1;

	return q;
}
//左旋转
NODE Lrotate(node*tempRoot)
{
	node *q = tempRoot->right;
	tempRoot->right = q->left;
	q->left = tempRoot;
	tempRoot = q;
	tempRoot->height = max(getHeight(&tempRoot->left),
		getHeight(&tempRoot->right)) + 1;

	q->height = max(getHeight(&q->left),
		getHeight(&q->right)) + 1;

	return q;
}
//右左旋转
NODE RLrotate(node*tempRoot)
{
	Lrotate(&tempRoot->left);
	return Rrotate(&tempRoot);
}
//左右旋转
NODE LRrotate(node*tempRoot)
{
	Rrotate(&tempRoot->right);
	return Lrotate(&tempRoot);
}
//插入数据
VOID _ins(node*tempRoot, T data)
{
	if (!tempRoot)
		tempRoot = new node(data);
	else if (data < tempRoot->data)
	{//因为数据要比根数据小,所以要插入在左边
		_ins(&tempRoot->left, data);
		//插入后判断平衡情况
		if (getHeight(&tempRoot->left) - getHeight(&tempRoot->right) > 1)
		{//如果不平衡(高度差为2),就旋转
			
			if (data < tempRoot->left->data)//4->3->2这种情况
				tempRoot = Rrotate(&tempRoot);//只进行右旋转
			else//4->2->3这种情况,如果只右旋,2为开头,显然是不对的
				tempRoot = RLrotate(&tempRoot);//需要右左旋转
		}//这里有另一种写法,判断符号的写法,不过太JB难,
	}	 //或者说我找到的那种教程与我平常的代码风格相差太大,我看不懂
	else if (data > tempRoot->data)
	{
		_ins(&tempRoot->right, data);
		if (getHeight(&tempRoot->right) - getHeight(&tempRoot->left) > 1)
		{
			if (data > tempRoot->right->data)
				tempRoot = Lrotate(&tempRoot);
			else
				tempRoot = LRrotate(&tempRoot);
		}
	}
	//插入了数据就要重新调整一次树的高度
	tempRoot->height = max(getHeight(&tempRoot->left), 
		getHeight(&tempRoot->right)) + 1;
}
//输出
VOID _midP(node*tempRoot)
{
	if (tempRoot)
	{
		_midP(&tempRoot->left);
		cout << tempRoot->data << ends;
		_midP(&tempRoot->right);
	}
}
//清空数据
VOID _clear(node*tempRoot)
{
	if (!tempRoot)
		return;
	_clear(&tempRoot->left);
	_clear(&tempRoot->right);
	delete tempRoot;
	tempRoot = NULL;
}
//找最大结点
NODE findMax(node*tempRoot)
{
	if (!tempRoot)
		return NULL;
	if (!tempRoot->right)
		return tempRoot;
	return findMax(&tempRoot->right);
}
//找最小结点
NODE findMin(node*tempRoot)
{
	if (!tempRoot)
		return NULL;
	if (!tempRoot->left)
		return tempRoot;
	return findMin(&tempRoot->left);
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值