AVL树C++代码实现

前言

C++实现的一个平衡二叉树, 参考了许夜3大佬的这篇文章,建议读完后再看我的代码。

这个类只是我项目的一部分,有些成员的实现不在这里,不用担心,不影响阅读,看到跳过就行。

如果对我的项目感兴趣的话,可以看这个链接,如果你觉得我写的不错,麻烦给俺个star~

代码实现

template<typename Key, typename Val, typename Compare = Less<Key>, typename Equal_ = Equal<Key>>
    class AVL_Tree {
    public:
        friend class Detail::AVL_Tree_Iterator<Key, Val, Compare, Equal_>;

        using Iterator = Detail::AVL_Tree_Iterator<Key, Val, Compare, Equal_>;

        using cIterator = STD::cIterator<Iterator, Bidirectional_iterator_tag>;

        using rIterator = STD::rIterator<Iterator, Bidirectional_iterator_tag>;

        using crIterator = STD::crIterator<Iterator, Bidirectional_iterator_tag>;

        using Self = AVL_Tree<Key, Val, Compare, Equal_>;

    private:
        struct Node {
            Pair<Key, Val> value;

            Node *left = nullptr, *right = nullptr, *last = nullptr;

            int height = 1;

            explicit Node(const Key &key, const Val &val, int height = 1) :
                    value({key, val}), height(height) {};

            explicit Node(const Key &key, Val &&val, int height = 0) :
                    value({key, move(val)}), height(height) {};

            const Key &key() const { return value.first; };

        };

        Node *root = nullptr, *val_begin = nullptr, *val_end = nullptr;

        Compare less = Less<Key>();

        Equal_ equal = Equal<Key>();

        Size size_ = 0;

        // 计算传入节点的左节点与右节点之差
        int height_difference(Node *node) const {
            if (!node) return 0;
            int left = node->left ? node->left->height : 0;
            int right = node->right ? node->right->height : 0;
            return left - right;
        };

        // 重新计算传入节点的高度
        void calculate_height(Node *node) const {
            int left = node->left ? node->left->height : 0;
            int right = node->right ? node->right->height : 0;
            node->height = left > right ? left + 1 : right + 1;
        }

        // link操作是为了更新子节点的last,并将子节点连接到父节点上,同时会重新计算父节点的高度,可以减少许多麻烦。
        void link(Node *parent, bool left, Node *child) const {
            if (parent) {
                if (left) parent->left = child;
                else parent->right = child;
                calculate_height(parent);
            }
            if (child) child->last = parent;
        };

        // 左旋
        Node *L_alpha(Node *node) {
            Node *n_right = node->right;
            link(node, false, n_right->left);
            link(n_right, true, node);
            return n_right;
        }

        // 右旋
        Node *R_alpha(Node *node) {
            Node *n_left = node->left;
            link(node, true, n_left->right);
            link(n_left, false, node);
            return n_left;
        }

        // 该函数的作用是在树被破坏时,重新平衡树。
        Node *balance(Node *node);

        // 内置版本的插入函数。
        Node *insert(Node *node, Node *&target);

        // 找到该节点下的最小值。
        static Node *the_min(Node *node);

        // 找到该节点下的最大值。
        static Node *the_max(Node *node);

        // 删除该节点下的最大值。
        Node *erase_max(Node *node);

        // 内置递归版本的删除函数。
        Node *erase(Node *node, const Key &key);

        // 将该节点的全部分支删除。
        void erase_from(Node *node);

    public:
        AVL_Tree() = default;

        ~AVL_Tree();

        void clear();

        Pair<Iterator, bool> insert(const Key &key, const Val &value);

        Pair<Iterator, bool> insert(const Key &key, Val &&value);

        bool erase(const Key &key);

        Iterator find(const Key &key) const;

    };
    
//----------------------------------------------------------------------------------------------------------------------

    template<typename Key, typename Val, typename Compare, typename Equal>
    typename AVL_Tree<Key, Val, Compare, Equal>::Node *
    AVL_Tree<Key, Val, Compare, Equal>::the_min(Node *node) {
        if (!node) return nullptr;
        while (node->left) node = node->left;
        return node;
    };

    template<typename Key, typename Val, typename Compare, typename Equal>
    typename AVL_Tree<Key, Val, Compare, Equal>::Node *
    AVL_Tree<Key, Val, Compare, Equal>::the_max(Node *node) {
        if (!node) return nullptr;
        while (node->right) node = node->right;
        return node;
    };

    template<typename Key, typename Val, typename Compare, typename Equal_>
    void AVL_Tree<Key, Val, Compare, Equal_>::erase_from(Node *node) {
        if (!node) return;
        erase_from(node->left);
        erase_from(node->right);
        Deallocate(node);
        --size_;
    };

    template<typename Key, typename Val, typename Compare, typename Equal_>
    typename AVL_Tree<Key, Val, Compare, Equal_>::Node
    *AVL_Tree<Key, Val, Compare, Equal_>::balance(Node *node) {
        int difference = height_difference(node); // 得到左右的节点高度差。
        //一共有六种情况(插入会出现四种,删除会出现六种),这里合并为四种。
        if (difference > 1) { // 本节点的左边太长
            if (height_difference(node->left) >= 0) {
                node = R_alpha(node);
            } else { // 本节点的左节点的右边比较长
                link(node, true, L_alpha(node->left));
                node = R_alpha(node);
            }
        } else if (difference < -1) { // 本节点的右边太长
            if (height_difference(node->right) <= 0) {
                node = L_alpha(node);
            } else { // 本节点的右节点的左边比较长
                link(node, false, R_alpha(node->right));
                node = L_alpha(node);
            }
        }
        return node;
    };

    template<typename Key, typename Val, typename Compare, typename Equal_>
    typename AVL_Tree<Key, Val, Compare, Equal_>::Node
    *AVL_Tree<Key, Val, Compare, Equal_>::insert(Node *node, Node *&target) {
        if (!node) { // 说明找到了合适的位置插入,将目标向上传递,终止递归。
            ++size_;
            return target;
        }
        if (less(target->key(), node->key())) // 目标小于本节点,向左边寻找。
            link(node, true, insert(node->left, target));
        else if (!equal(target->key(), node->key())) // 目标大于本节点,向右边寻找。
            link(node, false, insert(node->right, target));
        else { // 找到了相等值,给本节点重新赋值。
            node->value = move(target->value);
            Deallocate(target);
            target = node;
        }
        return balance(node);
    };

    template<typename Key, typename Val, typename Compare, typename Equal_>
    typename AVL_Tree<Key, Val, Compare, Equal_>::Node
    *AVL_Tree<Key, Val, Compare, Equal_>::erase_max(Node *node) {
        if (node->right) { // 当没有找到最大值时,继续递归寻找。
            link(node, false, erase_max(node->right));
        } else if (node->left) { // 找到最大值,但其还有左节点,我们将其值换上来,删掉左节点。
            STD::swap(node->value, node->left->value);
            link(node, true, erase_max(node->left));
        } else { // 找到最大值,并且它没有任何子节点,可直接删除。
            if (val_end == node) val_end = node->last;
            Deallocate(node);
            --size_;
            return nullptr;
        }
        return balance(node);
    };

    template<typename Key, typename Val, typename Compare, typename Equal_>
    typename AVL_Tree<Key, Val, Compare, Equal_>::Node
    *AVL_Tree<Key, Val, Compare, Equal_>::erase(Node *node, const Key &key) {
        if (!node) return nullptr; // 说明树中没有该目标,终止递归。
        if (less(key, node->key())) // 目标值小于当前值,向左继续寻找。
            link(node, true, erase(node->left, key));
        else if (!equal(key, node->key())) // 目标值大于当前值,向右继续寻找。
            link(node, false, erase(node->right, key));
        else { // 找到目标值
            if (node->left) { // 有子节点比较麻烦,我们选择置换上来当前节点左边的最大值,转而删除被置换的那个节点。
                STD::swap(node->value, the_max(node->left)->value);
                link(node, true, erase_max(node->left));
            } else { // 这里合并了两种情况(有右节点和无节点),直接删除该节点,将该节点的右节点向上传递。
                auto temp = node->right;
                if (node == val_begin) val_begin = temp;
                if (node == val_end) val_end = node->last;
                Deallocate(node);
                --size_;
                return temp;
            }
        }
        return balance(node);
    };

//----------------------------------------------------------------------------------------------------------------------

    template<typename Key, typename Val, typename Compare, typename Equal_>
    AVL_Tree<Key, Val, Compare, Equal_>::~AVL_Tree() {
        erase_from(root);
    }

    template<typename Key, typename Val, typename Compare, typename Equal_>
    Pair<typename AVL_Tree<Key, Val, Compare, Equal_>::Iterator, bool>
    AVL_Tree<Key, Val, Compare, Equal_>::insert(const Key &key, const Val &value) {
        Size record = size_;
        // 节点默认高度为1。
        Node *temp = Allocate<Node>(key, value, 1);
        if (!size_) {
            val_begin = temp;
            val_end = temp;
        } else if (less(key, val_begin->key())) {
            val_begin = temp;
        } else if (!less(key, val_end->key()) && !equal(key, val_end->key())) {
            val_end = temp;
        }
        root = insert(root, temp);
        root->last = nullptr;
        return {Iterator(temp, this), size_ != record};
    };

    template<typename Key, typename Val, typename Compare, typename Equal_>
    bool AVL_Tree<Key, Val, Compare, Equal_>::erase(const Key &key) {
        Size record = size_;
        root = erase(root, key);
        if (root) root->last = nullptr;
        return record != size_;
    };
  • 14
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值