C++实现AVL(自平衡二叉搜索树)

参考:清华大学邓俊辉老师《数据结构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;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值