红黑树的代码实现(c++ 20)

题记  

      最近甚是苦闷,因为没有组成队伍。于是为了排解无聊,决定手搓一棵红黑树。心想我连avl树都写完了,不如再搞红黑树。反正应该不难吧?(doge)但是写完我才后悔了,这东西真难写,为此我不得不参考许多了资料,尤其是B站的up主@木子喵neko 和@哈哈哈哈栋 的说明。

        红黑树和一般的二叉搜索树一样,都需要实现增加节点、删除节点、查询节点三个函数。查询函数和一般二叉树的情形完全一致。插入部分的代码基本就是照搬@哈哈哈哈栋 而 删除的办法则是参考@木子喵neko的做法。具体原因是前者的代码能直接看懂并且改造,但是关于删除的部分讲得却不那么方便代码实现。

        在弄清楚原理后,就要开始构建了。在构建之前,我们先准备一些辅助函数,比如左右旋转的函数,又比如安全检查节点颜色的函数(这个很重要,因为能防止外部节点作为空指针被访问),安全建立父子关系建立的函数。

       同时,我们也要做好释放空间的操作,比如析构函数就改写成析构的样式。

        然后,我就开开心心地开始了构建!

源码

//
// Created by Mirror on 24-11-29.
//

#ifndef BLACK_RED_TREE_HPP
#define BLACK_RED_TREE_HPP
#define RED 1
#define BLACK 0
#include <iostream>
typedef  struct Black_Red_Tree_Node {
    unsigned char color;
    int data;
    Black_Red_Tree_Node *left = nullptr;
    Black_Red_Tree_Node *right = nullptr;
    Black_Red_Tree_Node*parent=nullptr;
    explicit Black_Red_Tree_Node(const int data):color(BLACK),data(data){}
    void Right_handed_rotation(Black_Red_Tree_Node *root) {
        //LL
        if (root == nullptr || root->left == nullptr)return;
            Black_Red_Tree_Node* new_root = root ->left;
            Black_Red_Tree_Node* T2 = new_root->right;
            root->left = T2;
            if (T2 != nullptr) {
                T2->parent = root;
            }//更新某些的父节点指针需要检查
            new_root->parent = root->parent;
            if (root->parent != nullptr) {
                if (root->parent->left == root) {
                    root->parent->left = new_root;
                }else if (root->parent->right == root) {
                    root->parent->right = new_root;
                }
            }
            root->parent = new_root;
            new_root->right = root;
    }
    void Left_handed_rotation(Black_Red_Tree_Node *root) {
        //RR
        if (root == nullptr || root->right == nullptr)return;
        Black_Red_Tree_Node* new_root = root ->right;
        Black_Red_Tree_Node* T2 = new_root->left;
        root->right = T2;
        if (T2 != nullptr) {
            T2->parent = root;
        }//更新某些的父节点指针需要检查

        //新根的父节点也要改
        new_root->parent = root->parent;
        if (root->parent != nullptr) {
            if (root->parent->left == root) {
                root->parent->left = new_root;
            }else if (root->parent->right == root) {
                root->parent->right = new_root;
            }
        }
        root->parent = new_root;
        new_root->left = root;
    }
    static bool insert(Black_Red_Tree_Node* root , const int element) {
        Black_Red_Tree_Node* current = root;
        Black_Red_Tree_Node* previous = root;
        while (current != nullptr) {
            previous = current;
            if (current->data < element) {
                current = current ->right;
                continue;
            }
            if (current->data == element) {
                return false;
            }
            if (current->data > element) {
                current = current->left;
                //continue;
            }
        }
        if (previous != nullptr) {
            Black_Red_Tree_Node* NewNode = new Black_Red_Tree_Node(element);
            NewNode->parent = previous;
            NewNode->color = RED;//所有插入的节点都是红色的
            if (previous->data < element) {
                previous->right = NewNode;
            }else {
                previous->left = NewNode;
            }
            return true;
        }
        return false;
    }
    static std::pair<bool,Black_Red_Tree_Node*>Delete_Red_Leaf_Node(Black_Red_Tree_Node* node) {
        if (node == nullptr || node->color == BLACK || node->left != nullptr || node->right != nullptr)
            return {false,nullptr};
        Black_Red_Tree_Node *Parent = node->parent;
        if (Parent->left == node) {
            delete Parent->left;
            Parent->left = nullptr;
        }else {
            delete Parent->right;
            Parent->right = nullptr;
        }
        return {true,Parent};
    }//安全删除红色叶子节点
    std::pair<bool,Black_Red_Tree_Node*> insert(const int element) {
        Black_Red_Tree_Node* current = this;
        Black_Red_Tree_Node* previous = this;
        while (current != nullptr) {
            previous = current;
            if (current->data < element) {
                current = current ->right;
                continue;
            }
            if (current->data == element) {
                return {false, current};
            }
            if (current->data > element) {
                current = current->left;
                //continue;
            }
        }
        Black_Red_Tree_Node* NewNode = new Black_Red_Tree_Node(element);
        NewNode->parent = previous;
        NewNode->color = RED;//所有插入的节点都是红色的
        if (previous->data < element) {
            previous->right = NewNode;
            return {true,previous->right};
        }else {
            previous->left = NewNode;
        }
        return {true,previous->left};

    }
    std::pair<bool,Black_Red_Tree_Node*>find(const int key) {
        Black_Red_Tree_Node* current = this;
        Black_Red_Tree_Node* previous = this;
        while (current != nullptr) {
            previous = current;
            if (current->data < key) {
                current = current ->right;
                continue;
            }
            if (current->data == key) {
                break;
            }
            if (current->data > key) {
                current = current->left;
                //continue;
            }
        }
        if (current == nullptr) {
            return {false , previous};
        }
        return {true,current};
    }
    std::pair<bool,Black_Red_Tree_Node*>Lowest_Upper_Bound() {
        if (right == nullptr)return {false,this};
        Black_Red_Tree_Node* current = right;
        while (current->left!= nullptr) {
            current = current->left;
        }
        return {true , current};
    }
    std::pair<bool,Black_Red_Tree_Node*>Biggest_Lower_Bound() {
        if (left == nullptr)return {false,this};
        Black_Red_Tree_Node* current = left;
        while ( current->right != nullptr) {
            current = current->right;
        }
        return {true , current};
    }
    static bool isBlack(const Black_Red_Tree_Node* node) {
        return node == nullptr || node->color == BLACK;
        //实际上更安全的写法应该是
        //return node == nullptr ? 1 : node->color == BLACK;
    }//用于安全地检查节点是否为黑色(利用短路)
    static bool isRed(const Black_Red_Tree_Node* node) {
        return node != nullptr && node->color == RED;
        //等价写法为
        //return !isBlack(node);
    }//用于安全地检查节点是否为红色(利用短路)
    static bool set_Parent_Child_relationship(Black_Red_Tree_Node*Parent,Black_Red_Tree_Node*Child) {
        if (Parent == nullptr || Child == nullptr || Parent->data == Child->data || Parent == Child)return false;
        if (Parent->left != nullptr && Parent->data > Child->data)return false;
        if (Parent->right != nullptr && Parent->data < Child->data)return false;
        if (Parent->data > Child->data) {
            Parent->left = Child;
            Child->parent = Parent;
        }else {
            Parent->right = Child;
            Child->parent = Parent;
        }
        return true;
    }//安全地建立父子关系
    static bool Delete_From_Root(Black_Red_Tree_Node* root) {
        if (root != nullptr) {
            root->parent = nullptr;
            delete root;
            return true;
        }
        return false;
    }
    ~Black_Red_Tree_Node() {
        if (left != nullptr) {
            delete left;
            left = nullptr;
        }
        if (right != nullptr) {
            delete right;
            right = nullptr;
        }
        if (parent != nullptr) {
            if (parent->left == this) {
                parent->left = nullptr;
            }else if (parent->right ==this){
                parent->right = nullptr;
            }
            parent = nullptr;
        }
        //递归析构二叉树
        // std::cout << "~Black_Red_Tree_Node"<<std::endl;
    }//注意:不能delete parent,否则会陷入死循环,因此直接解除双方的父子关系即可
} BRtree_node;

struct Black_Red_Tree{
    BRtree_node* root;
    explicit Black_Red_Tree():root(nullptr){}
    explicit Black_Red_Tree(const int e) {
        root = new BRtree_node(e);
    }
    std::pair<bool,BRtree_node*> insert(const int element) {
        if (root != nullptr) {
            Black_Red_Tree_Node* current = root->insert(element).second;
            Black_Red_Tree_Node* location = current;
            //获取当前插入节点的位置
             while (Black_Red_Tree_Node::isRed(current->parent)) {
                 if (current->parent == current->parent->parent->left) {
                     //LXx
                     Black_Red_Tree_Node* uncle = current->parent->parent->right;
                     if (Black_Red_Tree_Node::isRed(uncle) ) {
                         //Lxr
                         current->parent->color = BLACK;
                         uncle->color = BLACK;
                         current->parent->parent->color = RED;
                         current = current->parent->parent;
                     }else /*if(Black_Red_Tree_Node::isBlack(uncle))*/{
                         //LRb
                         if (current == current->parent->right) {
                             //调整为LLb
                             current = current->parent;
                             current->Left_handed_rotation(current);
                         }
                         //LLb
                         current->parent->color = BLACK;
                         current->parent->parent->color = RED;
                         current->parent->parent->Right_handed_rotation(current->parent->parent);
                     }
                 }
                 else/*if (current->parent = current->parent->parent->right)*/ {
                     //RXx
                     Black_Red_Tree_Node* uncle = current->parent->parent->left;
                     if (Black_Red_Tree_Node::isRed(uncle) ) {
                         //Rxr
                         current->parent->color = BLACK;
                         uncle->color = BLACK;
                         current->parent->parent->color = RED;
                         current = current->parent->parent;
                     }else /*if(Black_Red_Tree_Node::isBlack(uncle))*/{
                         //RLb
                         if (current == current->parent->left) {
                             //调整为RRb
                             current = current->parent;
                             current->Right_handed_rotation(current);
                         }
                         //RRb
                         current->parent->color = BLACK;
                         current->parent->parent->color = RED;
                         current->parent->parent->Left_handed_rotation(current->parent->parent);
                     }
                 }
             }
            RenewRoot();
            //因为左旋和右旋可能会改变根的位置,所以要维护根节点位置
            root->color = BLACK;
            //染色操作可能会导致根节点变色,于是要维护黑色
            return {true,location};
        }
        root = new Black_Red_Tree_Node(element);
        return {true,root};
    }
    std::pair<bool,BRtree_node*>find(const int key) {
        if (root == nullptr) {
            //std::cout << "[ root == nullptr ] Failed to search "<<key<<std::endl;
            return {false,root};
        }
        std::pair<bool,BRtree_node*>res = root->find(key);
        if (res.first) {
            //std::cout <<"key : "<<key<< " has been found at "<<res.second<<std::endl;
        }else {
            //std::cout << "[ key isn't exist at the BR_Tree ] Failed to search"<<std::endl;
        }
        return res;
    }
    bool RenewRoot() {
        if (root == nullptr)return false;
        while (root->parent != nullptr) {
            root = root->parent;
        }
        return true;
    }
    std::pair<bool,BRtree_node*> Delete(const int key) {
        std::pair<bool,BRtree_node*> Find = find(key);
        bool exist = Find.first;//用于防止重复删除节点
        if (!exist)return {false,Find.second};
        BRtree_node* target = Find.second;
        //删除红色节点
        if (Black_Red_Tree_Node::isRed(target)) {
            BRtree_node* Left = target->left;
            BRtree_node* Right = target->right;
            if (Left == nullptr && Right == nullptr) {
                return Black_Red_Tree_Node::Delete_Red_Leaf_Node(target);
            }//直接删除红色叶子节点
            if (Left != nullptr) {
                Black_Red_Tree_Node*NewTarget = target->Biggest_Lower_Bound().second;
                std::swap(target->data,NewTarget->data);
                target = NewTarget;
                //更新目标删除节点
                if (Black_Red_Tree_Node::isRed(target)) {
                    Black_Red_Tree_Node*Parent = target->parent;
                    Black_Red_Tree_Node*LeftChild = target->left;
                    target->left = nullptr;
                    Parent->right = nullptr;
                    Black_Red_Tree_Node::set_Parent_Child_relationship(Parent,LeftChild);
                    delete target;
                    exist = false;
                }else {
                    goto Delete_Black_Node;
                    //接替的节点为黑色,直接转换为删除黑色节点的情形,所以使用goto语句进入下文
                }
            }else /* if(Right != nullptr) */{
                Black_Red_Tree_Node*NewTarget = target->Lowest_Upper_Bound().second;
                std::swap(target->data,NewTarget->data);
                target = NewTarget;
                //更新目标删除节点
                if (Black_Red_Tree_Node::isRed(target)) {
                    Black_Red_Tree_Node*Parent = target->parent;
                    Black_Red_Tree_Node*RightChild = target->right;
                    target->right = nullptr;
                    Parent->left = nullptr;
                    Black_Red_Tree_Node::set_Parent_Child_relationship(Parent,RightChild);
                    delete target;
                    exist = false;
                }else {
                    goto Delete_Black_Node;
                    //接替的节点为黑色,直接转换为删除黑色节点的情形,所以使用goto语句进入下文
                }
            }
            //所要删除的红色节点的 接替的前驱/后驱节点若为红色
            //先交换数据,然后简单删除接替的红色节点
        }else {
            Delete_Black_Node:
            BRtree_node* Left = target->left;
            BRtree_node* Right = target->right;
            //删除黑色节点的情况比较复杂
            //1、我们先讨有论接替节点且节点为红色或者(黑色)的情形
            if (Left != nullptr) {
                Black_Red_Tree_Node*NewTarget = target->Biggest_Lower_Bound().second;
                std::swap(target->data,NewTarget->data);
                target = NewTarget;
                //更新目标删除节点
                if (Black_Red_Tree_Node::isRed(target)) {
                    Black_Red_Tree_Node*Parent = target->parent;
                    Black_Red_Tree_Node*LeftChild = target->left;
                    target->left = nullptr;
                    Parent->left = nullptr;
                    Black_Red_Tree_Node::set_Parent_Child_relationship(Parent,LeftChild);
                    delete target;
                    exist = false;
                }else {
                    goto Delete_Black_Node;
                    //接替的节点为黑色,直接转换为删除黑色节点的情形,所以使用goto语句回到前文
                }
            }else if(Right != nullptr) {
                Black_Red_Tree_Node*NewTarget = target->Lowest_Upper_Bound().second;
                std::swap(target->data,NewTarget->data);
                target = NewTarget;
                //更新目标删除节点
                if (Black_Red_Tree_Node::isRed(target)) {
                    Black_Red_Tree_Node*Parent = target->parent;
                    Black_Red_Tree_Node*RightChild = target->right;
                    target->right = nullptr;
                    Parent->left = nullptr;
                    Black_Red_Tree_Node::set_Parent_Child_relationship(Parent,RightChild);
                    delete target;
                    exist = false;
                }else {
                    goto Delete_Black_Node;
                    //接替的节点为黑色,直接转换为删除黑色节点的情形,所以使用goto语句回到前文
                }
            }else {
                __DELETE__BLACK_LEAF_NODE__:
                //2、没有接替节点,目标删除节点为黑色叶子节点
                //(1)根节点的情形
                if (target->parent == nullptr) {
                    if (exist) {
                        exist = false;
                        delete target;
                        target = nullptr;
                        root = nullptr;
                        //为什么这里不直接delete root呢?
                        //是因为在递归调整的过程中root不是根节点了,即 target 不一定等于 root
                        //
                    }
                    return {true , nullptr};

                }
                //(2)兄弟节点为黑色的情形
                if (target->parent->left == target && Black_Red_Tree_Node::isBlack(target->parent->right)) {
                    //(2.1)兄弟节点有红色子节点,拿来修复红黑树
                    Black_Red_Tree_Node*Parent = target->parent;
                    Black_Red_Tree_Node*Brother = Parent->right;
                    if (exist) {
                        exist = false;
                        delete target;
                        target = nullptr;
                        Parent->left = nullptr;
                    }
                    if (Black_Red_Tree_Node::isRed(Brother->right)) {
                        //RR
                        Brother->color = Parent->color;
                        Parent->Left_handed_rotation(Parent);
                        Brother->left->color = BLACK;
                        Brother->right->color = BLACK;
                    }else if (Black_Red_Tree_Node::isRed(Brother->left)) {
                        //RL
                        Black_Red_Tree_Node*FinalRoot = Brother->left;
                        FinalRoot->color = Parent->color;
                        Brother->Right_handed_rotation(Brother);
                        Parent->Left_handed_rotation(Parent);
                        FinalRoot->left->color = BLACK;
                        FinalRoot->right->color = BLACK;
                    }
                    //(2.2)兄弟节点没有红色子节点于是又要分情况讨论
                    //(2.2.1)父节点是红色的
                    else if (Black_Red_Tree_Node::isRed(Parent)) {
                        Parent->color = BLACK;
                        Brother->color = RED;
                    }
                    //(2.2.1)父节点是黑色的
                    else if (Black_Red_Tree_Node::isBlack(Parent)) {
                        Brother->color = RED;
                        target = Parent;
                        //递归回到上文去处理,同时假装target是一个外部节点
                        //这种幻想有利于处理
                        goto __DELETE__BLACK_LEAF_NODE__;
                    }
                }else if (target->parent->right == target && Black_Red_Tree_Node::isBlack(target->parent->left)) {
                    Black_Red_Tree_Node*Parent = target->parent;
                    Black_Red_Tree_Node*Brother = Parent->left;
                    if (exist) {
                        exist = false;
                        delete target;
                        target = nullptr;
                        Parent->right = nullptr;
                    }
                    if (Black_Red_Tree_Node::isRed(Brother->left)) {
                        //LL
                        Brother->color = Parent->color;
                        Parent->Right_handed_rotation(Parent);
                        Brother->left->color = BLACK;
                        Brother->right->color = BLACK;
                    }else if (Black_Red_Tree_Node::isRed(Brother->right )) {
                        //LR
                        Black_Red_Tree_Node*FinalRoot = Brother->right;
                        FinalRoot->color = Parent->color;
                        Brother->Left_handed_rotation(Brother);
                        Parent->Right_handed_rotation(Parent);
                        FinalRoot->left->color = BLACK;
                        FinalRoot->right->color = BLACK;
                    }
                    //(2.2)兄弟节点没有红色子节点于是又要分情况讨论
                    //(2.2.1)父节点是红色的
                    else if (Black_Red_Tree_Node::isRed(Parent)) {
                        Parent->color = BLACK;
                        Brother->color = RED;
                    }
                    //(2.2.2)父亲节点是黑色的
                    else if (Black_Red_Tree_Node::isBlack(Parent)) {
                        Brother->color = RED;
                        target = Parent;
                        goto __DELETE__BLACK_LEAF_NODE__;
                    }
                }
                //(3)兄弟节点为红色的情形,通过染色和旋转变为兄弟节点为黑色的情况,即情况二
                //旋转和染色这两部可以调换顺序
				//但是要注意的是,这个过程结束后要进行递归,这里采用的是goto语句实现
                else if (target->parent->left == target && Black_Red_Tree_Node::isRed(target->parent->right)) {
                    Black_Red_Tree_Node*Parent = target->parent;
                    Black_Red_Tree_Node*Brother = Parent->right;
                    //RR
                    Parent->Left_handed_rotation(Parent);
                    Parent->color = RED;
                    Brother->color = BLACK;
                    goto __DELETE__BLACK_LEAF_NODE__;
                }else if (target->parent->right == target && Black_Red_Tree_Node::isRed(target->parent->left)) {
                    Black_Red_Tree_Node*Parent = target->parent;
                    Black_Red_Tree_Node*Brother = Parent->left;
                    //LL
                    Parent->Right_handed_rotation(Parent);
                    Parent->color = RED;
                    Brother->color = BLACK;
                    goto __DELETE__BLACK_LEAF_NODE__;
                }
            }
        }
        RenewRoot();
        //更新根节点的原因是调整过程中可能会更改根节点的位置,所以要维护其位置
        return {true,nullptr};
    }
    static void TreeDestroy(Black_Red_Tree *T) {
        delete T;
        T = nullptr;
    }
    static std::pair<bool,BRtree_node*>find(BRtree_node*root ,const int key) {
        if (root == nullptr) {
            std::cout << "[ root == nullptr ]Failed to search "<<key<<std::endl;
            return {false,root};
        }
        std::pair<bool,BRtree_node*>res = root->find(key);
        if (res.first) {
            std::cout <<"key : "<<key<< " has been found at "<<res.second<<std::endl;
        }else {
            std::cout << "[ key isn't exist at the BR_Tree ]Failed to search"<<std::endl;
        }
        return res;
    }
    ~Black_Red_Tree() {
        delete root;
        root = nullptr;
        // std::cout<<"~Black_Red_Tree"<<std::endl;
    }
};
typedef Black_Red_Tree* BRtree_Ptr;
typedef const Black_Red_Tree*const Const_BR_Ptr;

void preOrder(const BRtree_node* T);
void midOrder(const BRtree_node* T);
void aftOrder(const BRtree_node* T);
void preOrder(BRtree_Ptr T);
void midOrder(BRtree_Ptr T);
void aftOrder(BRtree_Ptr T);
#endif //BLACK_RED_TREE_HPP

后记

        C++的STL库中的set和map都是用红黑树实现的,因此受到了很多人和组织的关注。但是事实上这种结构的代码非常不好写,主要是因为特殊情况繁多且上下文逻辑链巨长(这导致书写的效率不太高,当然不排除这是因为我自己的代码水平有限)。如果没有太高学习要求的话建议是直接用就行了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值