学弟讲数据结构·树·平衡二叉树

二叉排序树的相关概念

一、概念

平衡二叉树

  • 树中任意结点的平衡因子(左子树高度 - 右子树高度)绝对值不超过1
  • 树中的每个左子树和右子树都是AVL树
  • AVL树是特殊的二叉搜索树
  • AVL树的旋转操作是指在平衡因子大于1时, 通过旋转来调整树的结构, 使平衡因子不超过1

标记平衡因子(左子树高度 - 右子树高度)

该树为AVL树

二、实现

节点定义

template <class T>
struct AVLNode{
    T value;
    AVLNode<T> *leftSon;
    AVLNode<T> *rightSon;
    int height;
    AVLNode(T value,AVLNode<T> *leftSon,AVLNode<T> *rightSon,int height){
        this->value = value;
        this->leftSon = leftSon;
        this->rightSon = rightSon;
        this->height = height;
    }
};

1. 获取节点信息

//获取某节点的高度
template <class T>
int getHeight(AVLNode<T> *root){
    if(root == nullptr){
        return 0;
    }
    return root->height;
}

//获取节点的平衡因子
template <class T>
int getBalanceFactor(AVLNode<T> *root){
    if(root == nullptr){
        return 0;
    }
    return getHeight(root->leftSon) - getHeight(root->rightSon);
}

2. 判断

//判断是否平衡
template <class T>
bool isBalance(AVLNode<T> *root){
    if(root == nullptr){
        return true;
    }
    if(abs(getBalanceFactor(root)) > 1){
        return false;
    }
    return isBalance(root->leftSon) && isBalance(root->rightSon);
}

3. 旋转

3.1 左旋

  • AVL树若在右子树插入右孩子导致失衡时,需进行单左旋调整
  • 旋转围绕最小失衡子树根节点进行

图示

原本平衡的AVL树插入节点7后导致不平衡;
最小失衡子树的根节点为节点5

实现代码:

//左旋;root为最小失衡子树的根节点
template <class T>
AVLNode<T> *leftRotation(AVLNode<T> *root){
    AVLNode<T> *p = root->rightSon;
    root->rightSon = p->leftSon;
    p->leftSon = root;
    //改变指向后,更新结点对应的高度
    root->height = max(getHeight(root->leftSon),getHeight(root->rightSon))+1;
    p->height = max(getHeight(p->leftSon),getHeight(p->rightSon))+1;
    return p;
}

代码过程图示:


3.2 右旋

  • AVL树若在左子树插入左孩子导致失衡时,需进行单右旋调整
  • 旋转围绕最小失衡子树的根节点进行

图示

实现代码:

template <class T>
AVLNode<T>* rightRotation(AVLNode<T>* root){
    AVLNode<T> *p = root->leftSon;
    root->leftSon = p->rightSon;
    p->rightSon = root;
    root->height = max(getHeight(root->leftSon), getHeight(root->rightSon)) + 1;
    p->height = max(getHeight(p->leftSon), getHeight(p->rightSon)) + 1;
    return p;
}

代码过程图示:

3.3 先右旋后左旋

  • AVL树在右子树上插入左孩子导致失衡时,需进行先右旋后左旋调整
template <class T>
AVLNode<T>* rightLeftRotation(AVLNode<T> *root){
    root->rightSon = rightRotation(root->rightSon);
    return leftRotation(root);
}

图示:

其中,红色为插入节点;绿色为最小失衡子树的根节点


3.4 先左旋后右旋

  • AVL树在左子树上插入右孩子导致失衡时,需进行先左旋后右旋调整
template <class T>
AVLNode<T>* leftRightRotation(AVLNode<T> *root){
    root->leftSon = leftRotation(root->leftSon);
    return rightRotation(root);
}

图示:

其中,红色为插入节点;绿色为最小失衡子树的根节点

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值