Explicación detallada del árbol AVL (árbol binario equilibrado) | Implementación C/C++

naturaleza

El concepto de factor de equilibrio se introduce sobre la base del árbol BST, que requiere que la diferencia de altura entre los subárboles izquierdo y derecho de cualquier nodo no supere 1

Cuatro situaciones que requieren rotación

  • El árbol del niño izquierdo es demasiado alto: diestro
  • El árbol del niño derecho del niño derecho es demasiado alto: zurdo
  • El subárbol derecho del hijo izquierdo es demasiado alto: primero gire el hijo izquierdo hacia la izquierda y luego gire el nodo actual hacia la derecha (equilibrio izquierdo)
  • El subárbol izquierdo del hijo derecho es demasiado alto: primero gire a la derecha al hijo derecho y luego gire a la izquierda al nodo actual (equilibrio derecho)
#include <iostream>
#include <cmath>
#include <algorithm>

using namespace std;

// 定义节点类型
template<typename T>
struct Node {
    Node(T data = T()) : data_(data), left_(nullptr), right_(nullptr), height_(1) {}
    T data_;
    Node* left_;
    Node* right_;
    int height_; // 记录节点的高度
};

// AVL树
template<typename T>
class AVLTree {
public:
    AVLTree() : root_(nullptr) {}
    // 插入
    void insert(const T& val) {
        root_ = insert(root_,val);
    }
    // 删除
    void remove(const T& val) {
        root_ = remove(root_,val);
    }
private:
    Node<T>* root_; // 根节点
    // 返回节点的高度
    int height(Node<T> *node) {
        return node == nullptr ? 0 : node->height_;
    }
    // 右旋
    Node<T>* rightRotate(Node<T>* node);
    // 左旋
    Node<T>* leftRotate(Node<T>* node);
    // 左平衡
    Node<T>* leftBalance(Node<T>* node);
    // 右平衡
    Node<T>* rightBalance(Node<T>* node);
    // 插入
    Node<T>* insert(Node<T>* node, const T& val);
    // 删除
    Node<T>* remove(Node<T>* node, const T& val);
};

// 右旋
template<typename T>
Node<T>* AVLTree<T>::rightRotate(Node<T>* node) {
    // 节点旋转
    Node<T>* child = node->left_;
    node->left_ = child->right_;
    child->right_ = node;
    // 高度更新
    node->height_ = max(height(node->left_), height(node->right_)) + 1;
    child->height_ = max(height(child->left_), height(child->right_)) + 1;
    // 返回旋转后的子树的新根节点
    return child;
}

// 左旋
template<typename T>
Node<T>* AVLTree<T>::leftRotate(Node<T>* node) {
    // 节点旋转
    Node<T> *child = node->left_;
    node->right_ = child->left_;
    child->left_ = node;
    // 高度更新
    node->height_ = max(height(node->left_), height(node->right_)) + 1;
    child->height_ = max(height(child->left_), height(child->right_)) + 1;
    // 返回旋转后的子树的新根节点
    return child;
}

// 左平衡 先对node的左子树左旋,再对node右旋
template<typename T>
Node<T>* AVLTree<T>::leftBalance(Node<T> *node) {
    node->left_ = leftRotate(node->left_);
    return rightRotate(node);
}

// 右平衡 先对node的右子树右旋,再对node左旋
template<typename T>
Node<T>* AVLTree<T>::rightBalance(Node<T> *node) {
    node->right_ = rightRotate(node->right_);
    return leftRotate(node);
}

// 插入
template<typename T>
Node<T>* AVLTree<T>::insert(Node<T> *node, const T &val) {
    // 递归结束 找到插入的位置
    if (node == nullptr) return new Node<T>(val);

    if (node->data_ > val) {
        node->left_ = insert(node->left_,val);
        // 判断是否失衡
        if (height(node->left_) - height(node->right_) > 1) {
            if (height(node->left_->left_) >= height(node->left_->right_)) {
                // 左孩子的左子树太高
                node = rightRotate(node);
            } else {
                // 左孩子的右子树太高
                node = leftBalance(node);
            }
        }
    } else if (node->data_ < val) {
        node->right_ = insert(node->right_,val);
        if (height(node->right_) - height(node->left_) > 1) {
            if (height(node->right_->right_) >= height(node->right_->left_)) {
                node = leftRotate(node);
            } else {
                node = rightBalance(node);
            }
        }
    } else {
        // 找到相同节点 不需要向下递归 直接向上回溯
    }

    // 因为子树添加了新的节点 所以在递归的时候需要更新节点高度
    node->height_ = max(height(node->left_), height(node->right_)) + 1;

    return node;
}

// 删除操作 从叶子节点中选出一个节点 进行替换
template<typename T>
Node<T>* AVLTree<T>::remove(Node<T> *node, const T &val) {
    if (node == nullptr) {
        return nullptr;
    }

    if (node->data_ > val) {
        node->left_ = remove(node->left_,val);
        if (height(node->right_) - height(node->left_) > 1) {
            if (height(node->right_->right_) >= height(node->right_->left_)) {
                node = leftRotate(node);
            } else {
                node = rightBalance(node);
            }
        }
    } else if (node->data_ < val) {
        node->right_ = remove(node->right_,val);
        if (height(node->left_) - height(node->right_) > 1) {
            if (height(node->left_->left_) >= height(node->left_->right_)) {
                node = rightRotate(node);
            } else {
                node = leftBalance(node);
            }
        }
    } else {
        // 找到节点
        // 如果有两个孩子
        if (node->left_ != nullptr && node->right_ != nullptr) {
            // 谁高删谁的节点
            if (height(node->left_) >= height(node->right_)) {
                Node<T>* pre = node->left_;
                while (pre->right_ != nullptr) {
                    pre = pre->right_;
                }
                node->data_ = pre->data_;
                node->left_ = remove(node->left_,pre->data_);
            } else {
                Node<T>* pre = node->right_;
                while (pre->left_ != nullptr) {
                    pre = pre->left_;
                }
                node->data_ = pre->data_;
                node->right_ = remove(node->right_,pre->data_);
            }
        } else {
            // 如果只有一个孩子
            if (node->left_ != nullptr) {
                Node<T>* left = node->left_;
                delete node;
                return left;
            } else if (node->right_ != nullptr) {
                Node<T>* right = node->right_;
                delete node;
                return right;
            } else {
                delete node;
                return nullptr;
            }
        }
    }

    // 更新节点高度
    node->height_ = max(height(node->left_), height(node->right_)) + 1;
    return node;
}

análisis de rendimiento

  • Insertar un nodo en un árbol AVL requiere como máximo dos rotaciones para restablecer el equilibrio

Insertar un nodo hará que la altura del subárbol donde se encuentra el nodo aumente en 1, pero la rotación disminuirá el subárbol donde se encuentra el nuevo nodo en 1, por lo que insertar un nodo en un árbol AVL solo necesita dos rotaciones como máximo

  • La eliminación del árbol AVL de un nodo requiere como máximo rotaciones O (logN) para restablecer el equilibrio

Eliminar un nodo reducirá el subárbol donde se encuentra el nodo en 1, y la rotación reducirá el subárbol donde se encuentra el nodo en 1, por lo que en el peor de los casos se requieren rotaciones O(logN)

[Error en la transferencia de imagen del enlace externo, el sitio de origen puede tener un mecanismo de enlace antirrobo, se recomienda guardar la imagen y cargarla directamente (img-K38jGI6Q-1678955045720) (C:\Users\gnezd\AppData\Roaming\Typora \typora-user-images\ image-20230316155305771.png)]

Después de eliminar el nodo X, el factor de equilibrio de R4 se convierte en -2 y R4 es zurdo; el factor de equilibrio de R3 se convierte en 2 y R3 es diestro; el factor de equilibrio de R2 se convierte en -2 y R2 es zurdo- diestro; el factor de equilibrio de R1 se convierte en 2, y R1 diestro

Cuando el factor de equilibrio desde el nodo raíz hasta el nodo principal del nodo que se va a eliminar es -1 y +1 alternativamente, una vez que se elimina el nodo y se activa la rotación, se requieren rotaciones de inicio de sesión

Supongo que te gusta

Origin blog.csdn.net/blll0/article/details/129590539
Recomendado
Clasificación