04-树5 Root of AVL Tree (25分)

本文介绍了AVL树的平衡因子和四种旋转操作:LL旋转、RR旋转、LR旋转和RL旋转,提供了C++实现,包括插入节点和维护平衡的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/*
平衡二叉树(Balanced Binary Tree)(AVL Tree)
平衡因子(Balance Factor):BF(T) = LHeight - RHeight
|BF| <= 1

调整:
1. 左子树的左边插入,LL插入:向右旋转(顺时针)。-> 为何叫做左单旋?唉,真是让人难以理解。
2. 右子树的右边插入,RR插入:向左旋转(逆时针)。
3. 左子树的右边插入,LR插入:对左子树进行逆时针旋转,再顺时针旋转。
4. 右子树的左边插入,RL插入:对右子树进行顺时针旋转,在逆时针旋转。
*/

#ifndef AVLTREE_H
#define AVLTREE_H

#include <algorithm>    //std::max
using namespace std;

using T = int;          //Element Type
class AVLTree {
    //节点类
    struct Node {
        T data;
        Node *left, *right;
        int height;

        Node(const T &data, Node* const &left=nullptr, Node* const &right=nullptr, const int &height=0):
            data(data), left(left), right(right), height(height) {}
    };
public:
    AVLTree();                      //生成一颗空树。
//    ~AVLTree();
    void insert(const T &data);     //提供的对外接口,友好化。插入一个节点(元素)。
    int printRoot() {
        return root->data;
    }

private:
    int getHeight(Node* const &node);
    void updateHeight(Node *&node);
    //插入、旋转和更新树高在此函数操作。
    void insertInNode(Node *&node, const T &data);
    void rotateWithLeftChild(Node *&node);      //LL旋转 -> 顺时针
    void rotateWithRightChild(Node *&node);     //RR旋转
    void doubleRotateWithLeft(Node *&node);     //LR旋转 -> 左子树逆时针,再顺时针。
    void doubleRotateWithRight(Node *&node);    //RL旋转

    Node *root;     //树根节点。
    int nodeCnt;    //树节点个数。
};

AVLTree::AVLTree():
    root(nullptr),
    nodeCnt(0) {}

inline
int AVLTree::getHeight(Node* const &node) {
    return node == nullptr ? -1 : node->height;
}

inline  
void AVLTree::updateHeight(Node *&node) {
    node->height = max(getHeight(node->left), getHeight(node->right)) + 1;
}

void AVLTree::insert(const T &data) {
    insertInNode(root, data);
}


void AVLTree::insertInNode(Node *&node, const T &data) {
    if(node == nullptr) {
        node = new Node(data);
        ++nodeCnt;
    }
    else if(data < node->data) {
        insertInNode(node->left, data);
        if(getHeight(node->left) - getHeight(node->right) == 2) {
            if(data < node->left->data)
                rotateWithLeftChild(node);
            else
                doubleRotateWithLeft(node);
        }
    }
    else if(data > node->data) {
        insertInNode(node->right, data);
        if(getHeight(node->left) - getHeight(node->right) == -2) {
            if(data > node->right->data)
                rotateWithRightChild(node);
            else
                doubleRotateWithRight(node);
        }
    }
    //若相同的数据存在。Duplicate; do nothing.
    updateHeight(node);
}

//node 一定有一个左孩子
void AVLTree::rotateWithLeftChild(Node *&node) {
    Node *tmp = node->left;
    node->left = tmp->right;
    tmp->right = node;
    //更新树高。此时原node是tmp的右孩子,所以先更新node。
    updateHeight(node);
    updateHeight(tmp);      //tmp->height = max(getHeight(tmp->left), node->height) + 1;
    //返回新的根节点
    node = tmp;
}

//node 一定有一个右孩子
void AVLTree::rotateWithRightChild(Node *&node) {
    Node *tmp = node->right;
    node->right = tmp->left;
    tmp->left = node;

    updateHeight(node);
    updateHeight(tmp);
    node = tmp;
}

void AVLTree::doubleRotateWithLeft(Node *&node) {
    rotateWithRightChild(node->left);
    rotateWithLeftChild(node);
}

void AVLTree::doubleRotateWithRight(Node *&node) {
    rotateWithLeftChild(node->right);
    rotateWithRightChild(node);
}

#endif // AVLTREE_H

#include <iostream>
using namespace std;

int main(void) {
    AVLTree avl;
    int n, data;
    cin >> n;
        for(int i(0); i < n; ++i) {
        cin >> data;
        avl.insert(data);
    }
	cout << avl.printRoot() << endl;

    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值