参考:清华大学邓俊辉老师《数据结构C++语言实现》
AVL的插入操作,失衡点至少为插入节点的爷爷,一次修正后,整树不再失衡
AVL的删除操作,失衡点至少为插入节点的父亲,修正后,其祖先可能继续失衡
对于插入和删除操作来说,时间复杂度均为O(logn);
但是插入仅需O(1)次拓扑结构调整,删除则需要O(logn)次调整——致命缺陷(红黑树可以弥补)
代码实现:
定义:
//
// Created by Jayson on 2023/8/3.
//
#include "BST.h"
#include <cmath>
#include <iostream>
using namespace std;
template<typename T>
class AVL :public BST<T>{
public:
//基本操作
BinNode<T>* insert(T e);
bool remove(T e);
//辅助函数:
//节点是否平衡?
bool isBalanced(BinNode<T>* x);
//返回高的孩子
BinNode<T>* gettallerChild(BinNode<T>* x);
//失衡节点,找到其孙子,调用rotateAT,旋转过程根据结构不同可以简化为3+4重构
BinNode<T>* connect34(BinNode<T>* a,BinNode<T>* b,BinNode<T>*c,
BinNode<T>* T0, BinNode<T>* T1, BinNode<T>* T2, BinNode<T>* T3);
BinNode<T>* rotateAT(BinNode<T>* v);
};
函数实现:
//平衡判断
template<typename T>
bool AVL<T>::isBalanced(BinNode<T> *x) {
int val;
this->updateHeight(x->lchild);
this->updateHeight(x->rchild);
if(x->lchild && x->rchild){
val = abs(x->lchild->height - x->rchild->height);
}else if(!x->lchild && x->rchild){
val = abs(-1 - x->rchild->height);
}else if(x->lchild && !x->rchild){
val = abs(x->lchild->height - (-1));
}else{
val = 0;
}
return val <= 1;
}
template<typename T>
BinNode<T>* AVL<T>::gettallerChild(BinNode<T> *x) {
//返回高度更大的孩子,若左右孩子高度相同,则返回和父亲同侧者
this->updateHeight(x->lchild);
this->updateHeight(x->rchild);
BinNode<T>* lc = x->lchild;
BinNode<T>* rc = x->rchild;
if(lc && rc){
if(lc->height > rc->height){
return lc;
}else if(lc->height < rc->height){
return rc;
}else{
if(x->parent){//左右孩子高度相等,且x不是根
if(x->parent->lchild == x){
return lc;
}else{
return rc;
}
}else{//若左右孩子高度相等,且x是根,返回左孩子
return lc;
}
}
}else if(!lc && rc){
return rc;
}else if(lc && !rc){
return lc;
}else{
return lc;
}
}
//3+4重构
template<typename T>
BinNode<T>* AVL<T>::connect34(BinNode<T> *a, BinNode<T> *b, BinNode<T> *c, BinNode<T> *T0, BinNode<T> *T1,
BinNode<T> *T2, BinNode<T> *T3) {
/*
b
a c
T0 T1 T2 T3
* */
a->lchild = T0; if(T0)T0->parent = a;
a->rchild = T1; if(T1)T1->parent = a;
c->lchild = T2; if(T2)T2->parent = c;
c->rchild = T3; if(T3)T3->parent = c;
b->lchild = a;
a->parent = b;
b->rchild = c;
c->parent = b;
this->updateHeight(a);
this->updateHeight(c);
this->updateHeight(b);
return b;
}
template<typename T>
BinNode<T>* AVL<T>::rotateAT(BinNode<T> *v) {
BinNode<T>* p = v->parent;//父亲
BinNode<T>* g = p->parent;//爷爷
if(p == g->lchild){
if(v == p->lchild){//zig-zig
p->parent = g->parent;
return connect34(v,p,g,v->lchild,v->rchild,p->rchild,g->rchild);
}else{//zig-zag
v->parent = g->parent;
return connect34(p,v,g,p->lchild,v->lchild,v->rchild,g->rchild);
}
}else{
if(v == p->rchild){//zag-zag
p->parent = g->parent;
return connect34(g,p,v,g->lchild,p->lchild,v->lchild,v->rchild);
}else{//zag-zig
v->parent = g->parent;
return connect34(g,v,p,g->lchild,v->lchild,v->rchild,p->rchild);
}
}
}
template<typename T>
BinNode<T>* AVL<T>::insert(T e) {
BinNode<T>*& x = BST<T>::search(e);
if(x)return x;
x = new BinNode<T>(e,this->_hot);
this->_size++;
BinNode<T>* xx = x;
for(BinNode<T>* g = this->_hot; g; g = g->parent){
if(!isBalanced(g)){
BinNode<T>* v = gettallerChild(g);
v = gettallerChild(v);
if(!g->parent){//根失衡
g = this->_root = rotateAT(v);
}else{
int temp;
BinNode<T>*gp = g->parent;
if(g->parent->lchild == g)temp =1;
else temp = 2;
BinNode<T>* g = rotateAT(v);
if(temp ==1) gp->lchild = g;
else gp->rchild = g;
}
}else{
this->updateHeight(g);
}
}
return xx;
}
template<typename T>
bool AVL<T>::remove(T e) {
BinNode<T>*& x = BST<T>::search(e);
if(!x) return false;
//找到,删除操作
if(!x->rchild){
x = x->lchild;
}else if(!x->lchild){
x = x->rchild;
}else{
BinNode<T>* succ = x->succ();
swap(x->value,succ->value);
if(succ->parent == x){
x->rchild = succ->rchild;
if(succ->rchild)succ->rchild->parent = x;
this->_hot = x->parent;
delete succ;
}else{
BinNode<T>* w = succ->parent;
w->lchild = succ->rchild;
if(succ->rchild)succ->rchild->parent = w;
this->_hot = w;
delete succ;
}
}
this->_size--;
this->updateHeightAbove(this->_hot);
//删除完,验证平衡
for(BinNode<T>* g = this->_hot; g; g = g->parent){
if(!isBalanced(g)){
BinNode<T>* v = gettallerChild(g);
v = gettallerChild(v);
if(!g->parent){//根失衡
g = this->_root = rotateAT(v);
}else{
int temp;
BinNode<T>*gp = g->parent;
if(g->parent->lchild == g)temp =1;
else temp = 2;
BinNode<T>* g = rotateAT(v);
if(temp ==1) gp->lchild = g;
else gp->rchild = g;
}
}
this->updateHeight(g);
}
return true;
}