二叉平衡树实现
讲解原理的博客较多,这里只进行实现。
由于serch比较简单,我们着重实现insert操作。
代码:
struct AVLtreenode
{
int data; //可以换成键值对类型,比较键值
int bf; //平衡因子的值是左子树高度减去右子树的高度,因此+1代表左子树高1,0代表左右一样高,-1代表右子树高1.
AVLtreenode *lchild, *rchild;
AVLtreenode() : data(0), bf(0), lchild(NULL), rchild(NULL) {}
AVLtreenode(int val) : data(val), bf(0), lchild(NULL), rchild(NULL) {}
};
class AVLtree
{
typedef AVLtreenode node;
public:
bool insert(node *now, int value, bool &taller)
{
//树空,插入新节点
if (!now)
{
now = new node(value);
taller = true;
return true;
}
//存在相同值,插入失败,可以把这里改成key值,key值不能相同
if (value == now->data)
{
taller = false;
return false;
}
else if (value < now->data) //进入左子树
{
if (!insert(now->lchild, value, taller)) //进入左子树,如果插入失败返回false
return false;
if (taller)
{
switch (now->bf)
{
//原本左子树高1,现因左子树增高,需进行左平衡处理
case 1:
leftbalance(now);
taller = false;
break;
//原本左右子树平衡,现左子树增高
case 0:
now->bf = 1;
taller = true;
break;
//原本右子树高1,现左子树增高,左右子树平衡
case -1:
now->bf = 0;
taller = false;
break;
}
}
}
else //进入右子树
{
if (!insert(now->rchild, value, taller)) //进入右子树,如果插入失败返回false
return false;
if (taller)
{
switch (now->bf)
{
//原本左子树高,现因右子树增高,左右子树平衡
case 1:
now->bf = 0;
taller = false;
break;
//原本左右子树平衡,现右子树增高
case 0:
now->bf = -1;
taller = true;
break;
//原本右子树高1,现右子树增高,需进行右平衡处理
case -1:
rightbalance(now);
taller = false;
break;
}
}
}
return true;
}
private:
void L_rotate(node *&now) //左旋
{
node *right = now->rchild;
now->rchild = right->lchild;
right->lchild = now;
now = right;
}
void R_rotate(node *&now) //右旋
{
node *left = now->lchild;
now->lchild = left->rchild;
left->rchild = now;
now = left;
}
void leftbalance(node *&now)
{
node *lc = now->lchild;
if (lc->bf == 1) //新节点插在now的左孩子的左子树上
{
//修改now及左右孩子的平衡因子
now->bf = lc->bf = 0;
//右旋
R_rotate(now);
}
else //新节点插在now的左孩子的右子树上
{
//修改now及左右孩子的平衡因子
node *rd = lc->rchild;
if (rd->bf == 1)
{
now->bf = -1;
lc->bf = 0;
}
else if (rd->bf == 0)
{
now->bf = lc->bf = 0;
}
else
{
now->bf = 0;
lc->bf = 1;
}
rd->bf = 0;
//左右旋
L_rotate(now->lchild);
R_rotate(now);
}
}
void rightbalance(node *&now)
{
node *rc = now->rchild;
if (rc->bf == -1) //新节点插在now的右孩子的右子树上
{
now->bf = rc->bf = 0;
L_rotate(now);
}
else //新节点插在now的右孩子的左子树上
{
//修改now及左右孩子的平衡因子
node *ld = rc->lchild;
if (ld->bf == 1)
{
now->bf = 0;
rc = 0;
}
else if (ld->bf == 0)
{
now->bf = rc->bf = 0;
}
else
{
now->bf = 1;
rc->bf = 0;
}
ld->bf = 0;
//右左旋
R_rotate(now->rchild);
L_rotate(now);
}
}
};