平衡因子
插入:失衡处理
小树高度T0~3,高度为4333即可想明白为什么删除会向上传递。把4删除为3
template <typename T> BinNodePosi(T) AVL<T>::insert ( const T& e ) { //将关键码e插入AVL树中
BinNodePosi(T) & x = search ( e ); if ( x ) return x; //确认目标节点不存在
BinNodePosi(T) xx = x = new BinNode<T> ( e, _hot ); _size++; //创建新节点x
// 此时,x的父亲_hot若增高,则其祖父有可能失衡
for ( BinNodePosi(T) g = _hot; g; g = g->parent ) { //从x之父出发向上,逐层检查各代祖先g
if ( !AvlBalanced ( *g ) ) { //一旦发现g失衡,则(采用“3 + 4”算法)使之复衡,并将子树
FromParentTo ( *g ) = rotateAt ( tallerChild ( tallerChild ( g ) ) ); //重新接入原树
break; //g复衡后,局部子树高度必然复原;其祖先亦必如此,故调整随即结束
} else //否则(g依然平衡),只需简单地
updateHeight ( g ); //更新其高度(注意:即便g未失衡,高度亦可能增加)
} //至多只需一次调整;若果真做过调整,则全树高度必然复原
return xx; //返回新节点位置
} //无论e是否存在于原树中,总有AVL::insert(e)->data == e
删除:失衡处理
同理插入的旋转,删除复衡就是提上去,插入复衡就是拉下来
template <typename T> bool AVL<T>::remove ( const T& e ) { //从AVL树中删除关键码e
BinNodePosi(T) & x = search ( e ); if ( !x ) return false; //确认目标存在(留意_hot的设置)
removeAt ( x, _hot ); _size--; //先按BST规则删除之(此后,原节点之父_hot及其祖先均可能失衡)
for ( BinNodePosi(T) g = _hot; g; g = g->parent ) { //从_hot出发向上,逐层检查各代祖先g
if ( !AvlBalanced ( *g ) ) //一旦发现g失衡,则(采用“3 + 4”算法)使之复衡,并将该子树联至
g = FromParentTo ( *g ) = rotateAt ( tallerChild ( tallerChild ( g ) ) ); //原父亲
updateHeight ( g ); //并更新其高度(注意:即便g未失衡,高度亦可能降低)
} //可能需做Omega(logn)次调整——无论是否做过调整,全树高度均可能降低
return true; //删除成功
} //若目标节点存在且被删除,返回true;否则返回false
3+4重构
直接拼装:输入3点+4树,输出:上图
template <typename T> BinNodePosi(T) BST<T>::connect34 (
BinNodePosi(T) a, BinNodePosi(T) b, BinNodePosi(T) c,
BinNodePosi(T) T0, BinNodePosi(T) T1, BinNodePosi(T) T2, BinNodePosi(T) T3
) {
//*DSA*/print(a); print(b); print(c); printf("\n");
a->lc = T0; if ( T0 ) T0->parent = a;
a->rc = T1; if ( T1 ) T1->parent = a; updateHeight ( a );
c->lc = T2; if ( T2 ) T2->parent = c;
c->rc = T3; if ( T3 ) T3->parent = c; updateHeight ( c );
b->lc = a; a->parent = b;
b->rc = c; c->parent = b; updateHeight ( b );
return b; //该子树新的根节点
}
/******************************************************************************************
* BST节点旋转变换统一算法(3节点 + 4子树),返回调整之后局部子树根节点的位置
* 注意:尽管子树根会正确指向上层节点(如果存在),但反向的联接须由上层函数完成
******************************************************************************************/
template <typename T> BinNodePosi(T) BST<T>::rotateAt ( BinNodePosi(T) v ) { //v为非空孙辈节点
/*DSA*/if ( !v ) { printf ( "\a\nFail to rotate a null node\n" ); exit ( -1 ); }
BinNodePosi(T) p = v->parent; BinNodePosi(T) g = p->parent; //视v、p和g相对位置分四种情况
if ( IsLChild ( *p ) ) /* zig */
if ( IsLChild ( *v ) ) { /* zig-zig */ //*DSA*/printf("\tzIg-zIg: ");
p->parent = g->parent; //向上联接
return connect34 ( v, p, g, v->lc, v->rc, p->rc, g->rc );
} else { /* zig-zag */ //*DSA*/printf("\tzIg-zAg: ");
v->parent = g->parent; //向上联接
return connect34 ( p, v, g, p->lc, v->lc, v->rc, g->rc );
}
else /* zag */
if ( IsRChild ( *v ) ) { /* zag-zag */ //*DSA*/printf("\tzAg-zAg: ");
p->parent = g->parent; //向上联接
return connect34 ( g, p, v, g->lc, p->lc, v->lc, v->rc );
} else { /* zag-zig */ //*DSA*/printf("\tzAg-zIg: ");
v->parent = g->parent; //向上联接
return connect34 ( g, v, p, g->lc, v->lc, v->rc, p->rc );
}
}