#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);
}