本文默认不讲左右旋转和左右结点失衡,总共六种情况的处理
先是AVL树的定义
typedef struct BSTNode {
ElemType data;
int bf;
struct BSTNode* lchild, * rchild;
}BSTNode, *BSTree;
然后是左右旋转
void R_Rotate(BSTree& p)
{
BSTree lc = p->lchild;
p->lchild = lc->rchild;
lc->rchild = p;
p = lc;
}
void L_Rotate(BSTree& p)
{
BSTree rc = p->rchild;
p->rchild = rc->lchild;
rc->lchild = p;
p = rc;
}
然后是对左结点和右结点做平衡
void LeftBalance(BSTree& T)
{
BSTree lc = T->lchild;
switch (lc->bf) {
case EH: {
T->bf = LH;
lc->bf = RH;
R_Rotate(T);
break;
}
case LH: {
T->bf = lc->bf = EH;
R_Rotate(T);
break;
}
case RH: {
BSTree rd = lc->rchild;
switch (rd->bf) {
case LH: {
T->bf = RH;
lc->bf = EH;
break;
}
case EH: {
T->bf = lc->bf = EH;
break;
}
case RH: {
T->bf = EH;
lc->bf = LH;
break;
}
}
rd->bf = EH;
L_Rotate(T->lchild);
R_Rotate(T);
}
}
}
void RightBalance(BSTree& T)
{
BSTree rc = T->rchild;
switch (rc->bf) {
case EH: {
T->bf = RH;
rc->bf = LH;
L_Rotate(T);
break;
}
case RH: {
T->bf = rc->bf = EH;
L_Rotate(T);
break;
}
case LH: {
BSTree ld = rc->lchild;
switch (ld->bf) {
case RH: {
T->bf = LH;
rc->bf = EH;
break;
}
case EH: {
T->bf = rc->bf = EH;
break;
}
case LH: {
T->bf = EH;
rc->bf = RH;
break;
}
}
ld->bf = EH;
R_Rotate(T->rchild);
L_Rotate(T);
}
}
}
首先是在递归情况下用isshort来标记是否变短,当isshort为true,且变短的子树在左并且本身是右高,或者变短的子树在右边并且本身是左高,那么直接就对该节点做左结点平衡或右结点平衡
在找到key时有可以分为两种情况
这里把要删除的结点标记为d,d的后继结点标记为s,显然s不可能有左孩子
如果d的右孩子恰好为s,那么情况比较简单,可以直接让s顶替d结点即可,并查看原来d结点的平衡因子做相应的修改即可
如果d的右孩子不是s结点,则情况比较复杂,先看图
假设要删除的结点为d,后继为s,s拿出来后,可能要对s的双亲做平衡,甚至对s的某一个祖先做平衡,很难检查到,于是可以先对原来的右高的结点做处理,容易证明,对右高结点做左旋高度不变,此时有三种情况,如图
左边两种直接做左旋,再调节平衡因子即可,右边这种做左旋会失衡,因此暂时保留,最后递归回来时如果是右高,必然是这种情况,单独做RL型平衡即可
在代码的ClearRH函数中专门做调节,在s结点无右子树时返回一个TRUE,来表示让s的双亲的左孩子调整为NULL,其他递归回去,只需看是等高还是左高即可,一旦遇到等高将isshort变为false,然后不再需要调整,ClearRH代码如下
Status ClearRH(BSTree& T, bool& isshort, BSTree& S)
{
if (T->lchild == NULL) {
S = T;
if(T->rchild) {
T = T->rchild;
isshort = true;
return FALSE;
}
isshort = true;
return TRUE;
}
else {
if (T->bf == RH) {
switch (T->rchild->bf) {
case EH: {
T->bf = EH;
T->rchild->bf = LH;
L_Rotate(T);
}
case RH: {
T->bf = LH;
T->rchild->bf = LH;
L_Rotate(T);
}
}
}
if (ClearRH(T->lchild, isshort, S)) {
T->lchild = NULL;
}
if (isshort) {
if (T->bf == LH) {
T->bf = EH;
}
else if (T->bf == EH) {
T->bf = RH;
isshort = false;
}
else {
RightBalance(T);
isshort = true;
}
}
return FALSE;
}
}
最后是删除结点后,递归回来情形比较简单和AVL树的插入类似,比较简单,在此不再赘述,代码如下
Status DeleteAVL_v2(BSTree& T, KeyType key, bool& isshort)
{
if (T == NULL) {
return FALSE;
}
else if (EQ(key, T->data.key)) {
if (T->lchild == NULL && T->rchild == NULL) {
free(T);
T = NULL;
isshort = true;
return TRUE;
}
else if (T->lchild != NULL && T->rchild == NULL) {
BSTree temp = T;
T = T->lchild;
free(temp);
isshort = true;
return TRUE;
}
else if (T->rchild != NULL && T->lchild == NULL) {
BSTree temp = T;
T = T->rchild;
free(temp);
isshort = true;
return TRUE;
}
else {
if (T->rchild->lchild == NULL) {
BSTree temp = T;
T->rchild->lchild = T->lchild;
T = T->rchild;
switch (temp->bf) {
case LH: {
if (temp->lchild == EH) {
isshort = false;
}
LeftBalance(T);
break;
}
case EH:T->bf = LH; isshort = false; break;
case RH:T->bf = EH; isshort = true; break;
}
free(temp);
return TRUE;
}
else {
BSTree temp = NULL;
ClearRH(T->rchild, isshort, temp);
temp->lchild = T->lchild;
temp->rchild = T->rchild;
BSTree ST = T;
T = temp;
if (isshort) {
switch (ST->bf) {
case LH: {
if (T->lchild->bf == EH) {
isshort = false;
}
LeftBalance(T);
break;
}
case RH:T->bf = EH; break;
case EH:T->bf = LH; isshort = false; break;
}
}
else {
T->bf = ST->bf;
}
free(ST);
return TRUE;
}
}
}
else if (LT(key, T->data.key)) {
if (DeleteAVL_v2(T->lchild, key, isshort)) {
if (isshort) {
switch (T->bf) {
case LH:T->bf = EH; break;
case EH:T->bf = RH; isshort = false; break;
case RH: {
if (T->rchild->bf == EH) {
isshort = false;
}
RightBalance(T);
break;
}
}
}
return TRUE;
}
return FALSE;
}
else {
if (DeleteAVL_v2(T->rchild, key, isshort)) {
if (isshort) {
switch (T->bf) {
case RH:T->bf = EH; break;
case EH:T->bf = LH; isshort = false; break;
case LH: {
if (T->lchild->bf == EH) {
isshort = false;
}
LeftBalance(T);
break;
}
}
}
return TRUE;
}
return FALSE;
}
}
来源:CSDN
作者:fbryaio15
链接:https://blog.csdn.net/fbryaio15/article/details/103632212