ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

红黑树c++

2021-02-14 21:29:24  阅读:147  来源: 互联网

标签:Node rightTree parent color c++ 红黑树 leftTree 节点


红黑树


具体的参考资料:
链接: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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有