AVL-Tree

AVL树是一种高度平衡的二叉查找树,保证任意节点的两棵子树高度差不超过1。插入和删除可能导致不平衡,通过左旋、右旋和双旋来重新平衡。平衡因子用于检测不平衡,插入和删除操作涉及LL、LR、RR和RL四种情况的旋转。AVL树的查找、插入和删除操作的时间复杂度为O(logn)。
摘要由CSDN通过智能技术生成

AVL-Tree是计算机科学中最早被发明的自平衡二叉查找树,在AVL树中,任一节点对应的两棵子树的最大高度差为1,因此它也被称为高度平衡树。查找、插入和删除在平均和最坏情况下的时间复杂度都是O(log n)。增加和删除元素的操作则可能需要借由一次或多次旋转,以实现树的重新平衡。

节点的平衡因子为左子树高度减去右子树高度的绝对值。平衡因子大于1被认为是不平衡的,需要重新平衡。

左旋转:根节点的右节点称为新的根节点,同时,右节点的子节点作为之前根节点的右节点存在。

右旋转:根节点的左节点作为新的根节点,同时,左节点的子节点作为之前根节点的左节点存在。

AVL树的平衡分为4种情况

描述

旋转方式

LL

在根节点的左子树节点左子树插入节点破坏平衡

围绕根节点左子树根节点右旋转

LR

在根节点的左子树节点右子树插入节点破坏平衡

先围绕根节点左子树根节点左旋转,再围绕左子树根节点右旋转

RR

在根节点的右子树节点右子树插入节点破坏平衡

围绕根节点左子树根节点左旋转

RL

在根节点的右子树节点左子树插入节点破坏平衡

先围绕根节点右子树根节点右旋转,再围绕左子树根节点左旋转

AVL树的旋转很难理解,这里做个示例,下图是一个有5个节点,高度为2的avl二叉树:

 当平衡情况为LL时

 经过右旋转结果为

 当平衡结果为LR时(在节点左子树的右子树上添加节点),这是通过简单的右旋转无法得到avl树

 先绕根节点左子树根节点左旋转,得到

 

 在通过右旋转得到

 用gpt写一个avl树的代码,本代码用于查找区间数组中与目标区间有重叠的区间,但并不是解决目标问题的最佳方式,计算时间大于线性搜索,如下

class AVLTree {
public:
    AVLTree() : root(nullptr) {}
    ~AVLTree() { clear(root); }

    void insert(Interval interval);
    vector<Interval> findIntersectingIntervals(Interval targetInterval);

private:
    Node* root;

    int height(Node* node);
    int balanceFactor(Node* node);
    void fixHeight(Node* node);
    Node* rotateRight(Node* node);
    Node* rotateLeft(Node* node);
    Node* balance(Node* node);
    Node* insert(Node* node, Interval interval);
    void traverse(Node* node, Interval &targetInterval, vector<Interval>& result);
    void clear(Node* node);
};

void AVLTree::insert(Interval interval) {
    root = insert(root, interval);

}

vector<Interval> AVLTree::findIntersectingIntervals(Interval targetInterval) {
    vector<Interval> result;
    traverse(root, targetInterval, result);
    return result;
}

int AVLTree::height(Node* node) {
    return (node == nullptr) ? 0 : node->height;
}

int AVLTree::balanceFactor(Node* node) {
    return height(node->left) - height(node->right);
}

void AVLTree::fixHeight(Node* node) {
    int heightLeft = height(node->left);
    int heightRight = height(node->right);
    node->height = max(heightLeft, heightRight) + 1;
}

Node* AVLTree::rotateRight(Node* node) {
    Node* newNode = node->left;
     node->left = newNode->right;
    newNode->right = node;
    fixHeight(node);
    fixHeight(newNode);
    return newNode;
}

Node* AVLTree::rotateLeft(Node* node) {
    Node* newNode = node->right;
    node->right = newNode->left;
    newNode->left = node;
    fixHeight(node);
    fixHeight(newNode);
    return newNode;
}

Node* AVLTree::balance(Node* node) {
    fixHeight(node);
    int bf = balanceFactor(node);

    //balance factor = 2
    if (bf == 2) {
        if (balanceFactor(node->left) < 0) {
            node->left = rotateLeft(node->left); // LR left rotate first
        }
        return rotateRight(node); //LL right rotate
    }
    if (bf == -2) {
        if (balanceFactor(node->right) > 0) {
            node->right = rotateRight(node->right); //RL right rotate first
        }
        return rotateLeft(node); //RR left rotate
    }
    return node;
}

Node* AVLTree::insert(Node* node, Interval interval) 
{
    if (node == nullptr) {
        Node* newNode = new Node{ interval, 1, nullptr, nullptr };
        return newNode;
    }
    if (interval.start < node->interval.start) {
        node->left = insert(node->left, interval);
    }
    else 
    {
        node->right = insert(node->right, interval);
    }
    return balance(node);
}

void AVLTree::traverse(Node* node, Interval &target, vector<Interval>& result) {

    Interval interval = node->interval;
    if (!(interval.end < target.start || interval.start > target.end))
    {
        result.push_back(interval);
    }

    if (node->left) {
        traverse(node->left, target, result);
    }

    if (node->right && (node->interval.start <= target.end)) {
        traverse(node->right, target, result);
    }

}

void AVLTree::clear(Node* node) {
    if (node) {
        clear(node->left);
        clear(node->right);
        delete node;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值