编程语言
首页 > 编程语言> > 红黑树c++

红黑树c++

作者:互联网

红黑树


具体的参考资料:
链接:https://pan.baidu.com/s/1Vgqo7_-yL_6hbxKknqaWRA
提取码:ozw6

#define BLACK 1
#define RED 0
#include <iostream>
using namespace std;
class bst
{
private:
    struct Node
    {
        //节点的值
        int value;
        bool color;
        Node *leftTree, *rightTree, *parent;
        Node() : value(0), color(RED), leftTree(nullptr), rightTree(nullptr), parent(nullptr)
        {
        }
        //返回节点的祖父
        Node *grandparent()
        {
            if (parent == nullptr)
            {
                return nullptr;
            }
            return parent->parent;
        }
        //返回节点的叔叔
        Node *uncle()
        {
            if (grandparent() == nullptr)
            {
                return nullptr;
            }
            if (parent == grandparent()->rightTree)
            {
                return grandparent()->leftTree;
            }
            else
            {
                return grandparent()->rightTree;
            }
        }
        //返回节点的兄弟
        Node *sibling()
        {
            if (parent->leftTree == this)
            {
                return parent->rightTree;
            }
            else
            {
                return parent->leftTree;
            }
        }
    };
    //右旋转
    void rotate_right(Node *p)
    {
        Node *gp = p->grandparent();
        Node *fa = p->parent;
        Node *y = p->rightTree;
        fa->leftTree = y;
        if (y != NIL)
        {
            y->parent = fa;
        }
        p->rightTree = fa;
        fa->parent = p;
        if (root == fa)
        {
            root = p;
        }
        p->parent = gp;
        if (gp != nullptr)
        {
            if (gp->leftTree == fa)
            {
                gp->leftTree = p;
            }
            else
            {
                gp->rightTree = p;
            }
        }
    }
    //左旋转
    void rotate_left(Node *p)
    {
        if (p->parent == nullptr)
        {
            root = p;
            return;
        }
        Node *gp = p->grandparent();
        Node *fa = p->parent;
        Node *y = p->leftTree;
        fa->rightTree = y;
        if (y != NIL)
        {
            y->parent = fa;
        }
        p->leftTree = fa;
        fa->parent = p;
        if (root == fa)
        {
            root = p;
        }
        p->parent = gp;
        if (gp != nullptr)
        {
            if (gp->leftTree == fa)
            {
                gp->leftTree = p;
            }
            else
            {
                gp->rightTree = p;
            }
        }
    }
    //遍历
    void inorder(Node *p)
    {
        if (p == NIL)
        {
            return;
        }
        if (p->leftTree)
        {
            inorder(p->leftTree);
        }
        cout << p->value << " ";
        if (p->rightTree)
        {
            inorder(p->rightTree);
        }
    }
    //输出颜色
    string outputColor(bool color)
    {
        return color ? "BLACK" : "RED";
    }
    //得到最小的孩子
    Node *getSmallestChild(Node *p)
    {
        if (p->leftTree == NIL)
        {
            return p;
        }
        return getSmallestChild(p->leftTree);
    }
    //删除孩子
    bool delete_child(Node *p, int data)
    {
        if (p->value > data)
        {
            if (p->leftTree == NIL)
            {
                return false;
            }
            //如果要删除的值比当前节点的小,就一直向左子树走
            return delete_child(p->leftTree, data);
        }
        else if (p->value < data)
        {
            if (p->rightTree == NIL)
            {
                return false;
            }
            //如果要删除的值比当前节点的大,就一直向右子树走
            return delete_child(p->rightTree, data);
        }
        else if (p->value == data)
        {
            //如果找到要删除的节点,判断右子树是否存在,如果不存在,那么该节点最多就只有一个字节点
            if (p->rightTree == NIL)
            {
                delete_one_child(p);
                return true;
            }
            //如果右子树存在就在右子树中找到最小的节点,与要删除的节点,交换值,但是不交换颜色,不破坏红黑数的结构
            Node *smallest = getSmallestChild(p->rightTree);
            swap(p->value, smallest->value);
            //删除这个最多只有一个孩子的节点
            delete_one_child(smallest);
            return true;
        }
        else
        {
            return false;
        }
    }
    void delete_one_child(Node *p)
    {
        Node *child = p->leftTree == NIL ? p->rightTree : p->leftTree;
        //只有根节点的情况
        if (p->parent == nullptr && p->leftTree == NIL && p->rightTree == NIL)
        {
            if (p != nullptr)
            {
                delete p;
            }
            p = nullptr;
            root = p;
            return;
        }
        //只有根节点加上左子树或者右子树
        if (p->parent == nullptr)
        {
            delete p;
            child->parent = nullptr;
            root = child;
            root->color = BLACK;
            return;
        }
        //将子节点上移,用子节点的代替要删除的节点 
        if (p->parent->leftTree == p)
        {
            p->parent->leftTree = child;
        }
        else
        {
            p->parent->rightTree = child;
        }
        child->parent = p->parent;
        if (p->color == BLACK)
        {
            //如果要删除的是黑色的节点,并且孩子是红色的,那么就直接让孩子节点变成黑色就直接达到平衡
            if (child->color == RED)
            {
                child->color = BLACK;
            }
            else
            {
                delete_case(child);
            }
        }
        delete p;
    }
    void delete_case(Node *p)
    {
        if (p->parent == nullptr)
        {
            p->color = BLACK;
            return;
        }
        //情形2
        if (p->sibling()->color == RED)
        {
            p->parent->color = RED;
            p->sibling()->color = BLACK;
            if (p == p->parent->leftTree)
            {
                rotate_left(p->parent);
            }
            else
            {
                rotate_right(p->parent);
            }
        }
        //情形3
        if (p->parent->color == BLACK && p->sibling()->color == BLACK && p->sibling()->leftTree->color == BLACK && p->sibling()->rightTree->color == BLACK)
        {
            p->sibling()->color = RED;
            delete_case(p->parent);
        }
        //情形4
        else if (p->parent->color == RED && p->sibling()->color == BLACK && p->sibling()->leftTree->color == BLACK && p->sibling()->rightTree->color == BLACK)
        {
            p->sibling()->color = RED;
            p->parent->color = BLACK;
        }
        else
        {
            //情形5
            if (p->sibling()->color == BLACK)
            {
                if (p == p->parent->leftTree && p->sibling()->leftTree->color == RED && p->sibling()->rightTree->color == BLACK)
                {
                    p->sibling()->color = RED;
                    p->sibling()->leftTree->color = BLACK;
                    rotate_right(p->sibling()->leftTree);
                }
                else if (p == p->parent->rightTree && p->sibling()->leftTree->color == BLACK && p->sibling()->rightTree->color == RED)
                {
                    p->sibling()->color = RED;
                    p->sibling()->rightTree->color = BLACK;
                    rotate_left(p->sibling()->rightTree);
                }
            }
            p->sibling()->color = p->parent->color;
            p->parent->color = BLACK;
            //情形6
            if (p == p->parent->leftTree)
            {
                p->sibling()->rightTree->color = BLACK;
                rotate_left(p->sibling());
            }
            else
            {
                p->sibling()->leftTree->color = BLACK;
                rotate_right(p->sibling());
            }
        }
    }
    void insert(Node *p, int data)
    {
        if (p->value >= data)
        {
            if (p->leftTree != NIL)
            {
                insert(p->leftTree, data);
            }
            else
            {
                Node *tmp = new Node();
                tmp->value = data;
                tmp->leftTree = tmp->rightTree = NIL;
                tmp->parent = p;
                p->leftTree = tmp;
                insert_case(tmp);
            }
        }
        else
        {
            if (p->rightTree != NIL)
            {
                insert(p->rightTree, data);
            }
            else
            {
                Node *tmp = new Node();
                tmp->value = data;
                tmp->leftTree = tmp->rightTree = NIL;
                tmp->parent = p;
                p->rightTree = tmp;
                insert_case(tmp);
            }
        }
    }
    void insert_case(Node *p)
    {
        //情形1 新节点N位于数的根上, 没有父节点
        if (p->parent == nullptr)
        {
            root = p;
            p->color = BLACK;
            return;
        }
        if (p->parent->color == RED)
        {
            //情形3 父节点和叔父节点都是红色
            if (p->uncle()->color == RED)
            {
                p->parent->color = p->uncle()->color = BLACK;
                p->grandparent()->color = RED;
                insert_case(p->grandparent());
            }
            else
            {
                //情形4 父节点是红色,叔父节点是黑色,并且插入的节点是父节点的右孩子, 父亲是祖父节点的左孩子
                if (p->parent->rightTree == p && p->grandparent()->leftTree == p->parent)
                {
                    rotate_left(p);
                    rotate_right(p);
                    p->color = BLACK;
                    p->leftTree->color = p->rightTree->color = RED;
                }
                //情形4 父节点是红色,叔父节点是黑色,并且插入的节点是父节点的左孩子, 父亲是祖父节点的右孩子
                else if (p->parent->leftTree == p && p->grandparent()->rightTree == p->parent)
                {
                    rotate_right(p);
                    rotate_left(p);
                    p->color = BLACK;
                    p->leftTree->color = p->rightTree->color = RED;
                }
                //情形4 父节点是红色,叔父节点是黑色,并且插入的节点是父节点的左孩子, 父亲是祖父节点的左孩子
                else if (p->parent->leftTree == p && p->grandparent()->leftTree == p->parent)
                {
                    p->parent->color = BLACK;
                    p->grandparent()->color = RED;
                    rotate_right(p->parent);
                }
                //情形4 父节点是红色,叔父节点是黑色,并且插入的节点是父节点的右孩子, 父亲是祖父节点的右孩子
                else if (p->parent->rightTree == p && p->grandparent()->rightTree == p->parent)
                {
                    p->parent->color = BLACK;
                    p->grandparent()->color = RED;
                    rotate_left(p->parent);
                }
            }
        }
    }
    void DeleteTree(Node *p)
    {
        if (!p || p == NIL)
        {
            return;
        }
        DeleteTree(p->leftTree);
        DeleteTree(p->rightTree);
        delete p;
    }

public:
    bst()
    {
        NIL = new Node();
        NIL->color = BLACK;
        root = nullptr;
    }
    ~bst()
    {
        if (root)
            DeleteTree(root);
        delete NIL;
    }
    void inorder()
    {
        if (root == nullptr)
            return;
        inorder(root);
        cout << endl;
    }
    void insert(int x)
    {
        //第一次插入
        if (root == nullptr)
        {
            root = new Node();
            root->color = BLACK;
            root->leftTree = root->rightTree = NIL;
            root->value = x;
        }
        else
        {
            insert(root, x);
        }
    }
    bool delete_value(int data)
    {
        return delete_child(root, data);
    }

private:
    Node *root, *NIL;
};

int main()
{
    bst tree;
    int array[] = {13, 8, 17, 1, 11, 15, 25, 6, 22, 27};
    for (int i = 0; i < 10; i++)
    {
        tree.insert(array[i]);
    }
    tree.inorder();
    cout << "--------------------------" << endl;
    tree.delete_value(17);
    tree.inorder();
}

在这里插入图片描述

标签:Node,rightTree,parent,color,c++,红黑树,leftTree,节点
来源: https://blog.csdn.net/qq_43812167/article/details/113811228