温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

C++数据结构之AVL树如何实现

发布时间:2022-06-10 09:59:39 阅读:148 作者:zzz 栏目:开发技术
C++开发者专用服务器限时活动,0元免费领,库存有限,领完即止! 点击查看>>

C++数据结构之AVL树如何实现

AVL树是一种自平衡的二叉搜索树,由Adelson-Velsky和Landis在1962年提出。它的特点是每个节点的左右子树高度差不超过1,因此能够保证在最坏情况下,查找、插入和删除操作的时间复杂度为O(log n)。本文将介绍如何在C++中实现AVL树。

1. AVL树的基本结构

AVL树的节点结构通常包含以下几个部分:

  • 数据域:存储节点的值。
  • 左子树指针:指向左子树的根节点。
  • 右子树指针:指向右子树的根节点。
  • 高度:记录当前节点的高度,用于平衡因子的计算。
struct AVLNode {
    int data;
    AVLNode* left;
    AVLNode* right;
    int height;

    AVLNode(int val) : data(val), left(nullptr), right(nullptr), height(1) {}
};

2. AVL树的基本操作

2.1 获取节点高度

为了计算平衡因子,我们需要一个函数来获取节点的高度。如果节点为空,则高度为0。

int getHeight(AVLNode* node) {
    if (node == nullptr) return 0;
    return node->height;
}

2.2 计算平衡因子

平衡因子是节点的左子树高度减去右子树高度。如果平衡因子的绝对值大于1,则需要进行旋转操作来恢复平衡。

int getBalanceFactor(AVLNode* node) {
    if (node == nullptr) return 0;
    return getHeight(node->left) - getHeight(node->right);
}

2.3 更新节点高度

在插入或删除节点后,需要更新节点的高度。

void updateHeight(AVLNode* node) {
    if (node == nullptr) return;
    node->height = 1 + std::max(getHeight(node->left), getHeight(node->right));
}

2.4 旋转操作

AVL树通过旋转操作来恢复平衡。主要有四种旋转方式:左旋、右旋、左右旋和右左旋。

2.4.1 左旋

左旋用于处理右子树过高的情况。

AVLNode* leftRotate(AVLNode* y) {
    AVLNode* x = y->right;
    AVLNode* T2 = x->left;

    x->left = y;
    y->right = T2;

    updateHeight(y);
    updateHeight(x);

    return x;
}

2.4.2 右旋

右旋用于处理左子树过高的情况。

AVLNode* rightRotate(AVLNode* x) {
    AVLNode* y = x->left;
    AVLNode* T2 = y->right;

    y->right = x;
    x->left = T2;

    updateHeight(x);
    updateHeight(y);

    return y;
}

2.4.3 左右旋

左右旋用于处理左子树的右子树过高的情况。

AVLNode* leftRightRotate(AVLNode* z) {
    z->left = leftRotate(z->left);
    return rightRotate(z);
}

2.4.4 右左旋

右左旋用于处理右子树的左子树过高的情况。

AVLNode* rightLeftRotate(AVLNode* z) {
    z->right = rightRotate(z->right);
    return leftRotate(z);
}

2.5 插入节点

插入节点的过程与普通二叉搜索树类似,但在插入后需要检查平衡因子并进行相应的旋转操作。

AVLNode* insert(AVLNode* root, int val) {
    if (root == nullptr) return new AVLNode(val);

    if (val < root->data) {
        root->left = insert(root->left, val);
    } else if (val > root->data) {
        root->right = insert(root->right, val);
    } else {
        return root; // 不允许插入重复值
    }

    updateHeight(root);

    int balance = getBalanceFactor(root);

    // 左子树过高
    if (balance > 1) {
        if (val < root->left->data) {
            return rightRotate(root);
        } else {
            return leftRightRotate(root);
        }
    }

    // 右子树过高
    if (balance < -1) {
        if (val > root->right->data) {
            return leftRotate(root);
        } else {
            return rightLeftRotate(root);
        }
    }

    return root;
}

2.6 删除节点

删除节点的过程也与普通二叉搜索树类似,但在删除后需要检查平衡因子并进行相应的旋转操作。

AVLNode* deleteNode(AVLNode* root, int val) {
    if (root == nullptr) return root;

    if (val < root->data) {
        root->left = deleteNode(root->left, val);
    } else if (val > root->data) {
        root->right = deleteNode(root->right, val);
    } else {
        if (root->left == nullptr || root->right == nullptr) {
            AVLNode* temp = root->left ? root->left : root->right;
            if (temp == nullptr) {
                temp = root;
                root = nullptr;
            } else {
                *root = *temp;
            }
            delete temp;
        } else {
            AVLNode* temp = findMin(root->right);
            root->data = temp->data;
            root->right = deleteNode(root->right, temp->data);
        }
    }

    if (root == nullptr) return root;

    updateHeight(root);

    int balance = getBalanceFactor(root);

    // 左子树过高
    if (balance > 1) {
        if (getBalanceFactor(root->left) >= 0) {
            return rightRotate(root);
        } else {
            return leftRightRotate(root);
        }
    }

    // 右子树过高
    if (balance < -1) {
        if (getBalanceFactor(root->right) <= 0) {
            return leftRotate(root);
        } else {
            return rightLeftRotate(root);
        }
    }

    return root;
}

3. 总结

AVL树通过旋转操作来保持树的平衡,从而保证了查找、插入和删除操作的高效性。本文介绍了如何在C++中实现AVL树的基本操作,包括插入、删除和旋转操作。通过理解和掌握这些基本操作,可以更好地应用AVL树来解决实际问题。

亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI

开发者交流群×