/* Rebalance sub-tree whose left branch has become short because of deletion */ AVLNode * AVL_RebalanceShorterLeft(AVLNode * self, int *height_changed) { #ifndef __CXC__ AVLNode *p = self; #else AVLNode *p; p = self; #endif switch (p->balance) { case Equal: p->balance = RightHigh; *height_changed = 0; break; case LeftHigh: /* taller (left) subtree was shortened */ p->balance = Equal; break; case RightHigh: { /* * shorter (left) subtree was shortened, violating * AVL rules */ AVLNode *q; q = p->right; switch (q->balance) { case Equal: *height_changed = 0; q->balance = LeftHigh; p = AVL_RotateLeft(p); break; case RightHigh: p->balance = q->balance = Equal; p = AVL_RotateLeft(p); break; case LeftHigh: p = AVL_DoubleRotateLeft(p); break; } break; } } return p; }
treenode *AVL_RightBalance(treenode * r) { treenode *x; treenode *w; x = r->Rchild; switch (x->bf) { case RH: r->bf = EH; x->bf = EH; r = AVL_RotateLeft(r); break; #ifdef AVL_DEBUG case EH: Error(5); break; #endif case LH: w = x->Lchild; switch (w->bf) { case EH: r->bf = EH; x->bf = EH; break; case LH: r->bf = EH; x->bf = RH; break; case RH: r->bf = LH; x->bf = EH; break; } w->bf = EH; x = AVL_RotateRight(x); r->Rchild = x; r = AVL_RotateLeft(r); } return r; }
/* * Rebalance sub-tree whose right branch has become heavier because of * insertion */ AVLNode * AVL_RebalanceHeavierRight(AVLNode * self, int *height_changed) { #ifndef __CXC__ AVLNode *root = self; #else AVLNode *root; root = self; #endif /* right-subtree has grown by one level */ switch (root->balance) { case LeftHigh: root->balance = Equal; *height_changed = 0; break; case Equal: root->balance = RightHigh; break; case RightHigh: { #ifndef __CXC__ AVLNode *rt = self->right; #else AVLNode *rt; rt = self->right; #endif switch (rt->balance) { case RightHigh: self->balance = Equal; rt->balance = Equal; root = AVL_RotateLeft(self); break; case LeftHigh: root = AVL_DoubleRotateLeft(self); break; default: break; } *height_changed = 0; break; } } return root; }
/* doubly rotate sub-tree and return new root (change balance as needed) */ AVLNode * AVL_DoubleRotateLeft(AVLNode * self) { #ifndef __CXC__ AVLNode *rt = self->right; AVLNode *lf = rt->left; AVLNode *root; #else AVLNode *rt; AVLNode *lf; AVLNode *root; rt = self->right; lf = rt->left; #endif switch (lf->balance) { case RightHigh: self->balance = LeftHigh; rt->balance = Equal; break; case Equal: self->balance = rt->balance = Equal; break; case LeftHigh: self->balance = Equal; rt->balance = RightHigh; break; } lf->balance = Equal; AVL_SetRight(self, AVL_RotateRight(rt)); root = AVL_RotateLeft(self); return root; }