C++实现红黑树

红黑树简介

红黑树是一个高效的平衡搜索树,保证最长路径不超过最短路径的两倍,因而近似平衡,保证了高度,也就保证了效率。增删查改时间复杂度都是O(logN)

性质:

  1. 每个结点不是红色就是黑色的。
  2. 根结点是黑色的。
  3. 如果一个结点是红色的,则它的两个子节点是黑色的(没有连续的红结点)
  4. 对于每个结点,从该结点到其所有后代叶节点的简单路径上,均包含相同数目的黑色结点(每条路径的黑色节点的数目相等
  5. 每个叶子结点都为黑色(此处叶子结点是空结点)

这几条规则保证了红黑树最长路径不超过最短路径的两倍(给个极端情况全黑色,然后在结点之间插入红色结点,即可得到结论)

结点的实现

三叉链实现RBtree,用KV存储结构,最后用枚举包含了相应的颜色。

树的实现

共有成员为空的构造函数,插入函数
私有成员为根,

红黑树的插入

为什么插入结点的颜色为红色好?
如果插入结点为黑色首先违背了第四条规则,每条路径黑色结点数目相同,虽然可以调整但是难调,我们原则上的保持第四条规则,所以选择插入红色节点。

方法:
首先判断是否为空树,接着找到插入结点,根据插入结点的情况来调整。 cur为插入结点,g为组父节点,p是父亲结点,u是叔叔结点
1. 如果插入结点为根结点,则直接插入,并且将根结点赋值为黑色。
2. 如果插入结点的父节点为黑色结点,那么直接插入。
3. 如果插入结点的父节点为红色结点,那么再次插入时,必然会有两个红色结点相连接,此时需要调整。

叔叔结点的情况和调整有关,叔叔的情况有以下几种:
叔叔存在且为红色
叔叔不存在
叔叔为黑色

插入分为三种情况

  1. 组父节点为黑色,父节点和叔叔结点为为红色,插入节点的为红色。
    此种情况下父亲结点和叔叔结点变为黑色,祖父结点变为红色,如果祖父结点是根结点则不影响,如果祖父结点不是根结点,则需要向上更新,
  2. 祖父结点为黑色,父亲结点为红色,叔叔结点(不存在或者为黑色),插入结点为红色。(单旋)

    • 第一种情况,叔叔不存在,cur为新增结点,
    • 第二种情况,叔叔存在且为黑色,parent的一边C一定存在且为黑色,cur为红色结点,cur此时不是新插入的结点,cur存在左右孩子,并且cur原先为黑色((cur此时左右为黑色吗?))

此时旋转来调整结点,观察p和cur均为左孩子,此时右单旋,p和cur均为右孩子,此时左单旋。

  1. 祖父结点为黑色,父亲结点为红色,叔叔结点(不存在或者为黑色),插入结点为红色。(双旋)
    • 第一种情况:u存在并且一定为黑色,cur不是新插入的结点,cur存在左右孩子,并且cur原先为黑色。
    • 第二种情况:u不存在,cur一定为新插入的结点。

实现代码如下

#include <iostream>
#include <assert.h>
using namespace std;

enum Colour
{
    RED,
    BLACK,
};

template <class K,class V>
struct RBTreeNode
{
    RBTreeNode* _left;
    RBTreeNode* _right;
    RBTreeNode* _parent;

    K _key;
    V _value;

    Colour _col;
    RBTreeNode(const K& key = K(), const V& value = V(), const Colour& color = RED)
        :_left(NULL)
        , _right(NULL)
        , _parent(NULL)
        , _key(key)
        , _value(value)
        , _col(color)
    {}
};

template <class K,class V>
class RBTree
{
    typedef RBTreeNode<K, V> Node;
public:
    RBTree()
        :_root(NULL)
    {}
    ~RBTree()
    {
        //if (_root)
        //  _root = _Destroy(_root);
    }
    RBTree(const RBTree<K, V>& rb)
    {
        if (this != &rb)
            _root = _Copy(_root);
    }
    RBTree<K, V> operator=(const RBTree<K, V>& rb)
    {
        if (*this != rb)
        {
            Node* tmp = _Copy(rb->_root);
            _root = _Destroy(_root);
            _root = tmp;
        }
        return *this;
    }
    bool Insert(const K& key, const V& value)
    {
        if (_root == NULL)
        {
            _root = new Node(key, value);
            _root->_col = BLACK;
            return true;
        }
        Node* pCur = _root;
        Node* pParent = NULL;
        while (pCur)
        {
            if (key < pCur->_key)
            {
                pParent = pCur;
                pCur = pCur->_left;
            }
            else if (key > pCur->_key)
            {
                pParent = pCur;
                pCur = pCur->_right;
            }
            else
                return false;
        }
        pCur = new Node(key, value);
        if (key < pParent->_key)
            pParent->_left = pCur;
        else
            pParent->_right = pCur;
        pCur->_parent = pParent;
        //未调整到根节点且父节点还是红色
        while (pCur != _root && pParent->_col == RED)
        {
            Node* grandfather = pParent->_parent;
            //先处理左边
            if (grandfather->_left == pParent)
            {
                Node* uncle = pParent->_right;
                //叔叔存在且为红色
                if (uncle && uncle->_col == RED)
                {
                    pParent->_col = uncle->_col = BLACK;
                    grandfather->_col = RED;
                    pCur = grandfather;
                    pParent = pCur->_parent;
                }
                //叔叔不存在或者叔叔为黑色
                else
                {
                    //pCur为pParent的右孩子
                    if (pParent->_right == pCur)
                    {
                        RotateL(pParent);
                        std::swap(pCur, pParent);
                    }
                    //pCur为pParent的左孩子
                    else
                    {
                        RotateR(grandfather);
                        grandfather->_col = RED;
                        pParent->_col = BLACK;
                    }
                }
            }
            //再处理右边的情况(与上述情况刚好位置相反)
            else
            {
                Node* uncle = grandfather->_left;
                //叔叔存在且为红
                if (uncle && uncle->_col == RED)
                {
                    pParent->_col = uncle->_col = BLACK;
                    pCur->_col = RED;
                    pCur = grandfather;
                    pParent = pCur->_parent;
                }
                //叔叔不存在或者叔叔为黑色
                else
                {
                    //pCur为pParent的左孩子
                    if (pParent->_left == pCur)
                    {
                        RotateR(pParent);
                        std::swap(pCur, grandfather);
                    }
                    //pCur为pParent的右孩子
                    else
                    {
                        RotateL(grandfather);
                        grandfather->_col = RED;
                        pParent->_col = BLACK;
                    }
                }
            }
        }
        _root->_col = BLACK;
        return true;
    }


    void RotateR(Node* parent)
    {
        assert(parent);
        Node* subL = parent->_left;
        Node* subLR = subL->_right;
        parent->_left = subLR;
        if (subLR)
            subLR->_parent = parent;
        Node* pparent = parent->_parent;
        subL->_right = parent;
        parent->_parent = subL;
        if (pparent->_left == parent)
        {
            pparent->_left = subL;
            subL->_parent = pparent;
        }
        else if (pparent->_right == parent)
        {
            pparent->_right = subL;
            subL->_parent = pparent;
        }
        else
        {
            _root = subL;
            subL->_parent = NULL;
        }
    }
    void RotateL(Node* parent)
    {
        assert(parent);
        Node* subR = parent->_right;
        Node* subRL = subR->_left;

        parent->_right = subRL;
        if (subRL)
            subRL->_parent = parent;

        Node* pparent = parent->_parent;
        subR->_left = parent;
        parent->_parent = subR;
        if (pparent->_left = subR->_parent)
        {
            pparent->_left = subR;
            subR->_parent = pparent;
        }
        else if (pparent->_right = subR->_parent)
        {
            pparent->_right = subR;
            subR->_parent = pparent;
        }
        else
        {
            _root = subR;
            subR->_parent = NULL;
        }
    }
    bool IsBalance()
    {
        if (NULL == _root)
            return true;
        if (_root->_col == RED)
            return false;
        size_t count = 0;
        Node* cur = _root;
        while (cur)
        {
            if (cur->_col == BLACK)
                count++;
            cur = cur->_left;
        }
        size_t k = 0;
        _IsBalance(_root, count, k);
    }
    void InOrder()
    {
        _Inorder(_root);
        cout << endl;
    }


private:
    bool _IsBalance(Node* _root, size_t count, size_t k)
    {
        if (_root == NULL)
            return true;
        if (_root->_parent&&_root->_col == _root->_parent->_col == RED)
            return false;
        if (_root->_col == BLACK)
            k++;
        if (_root->_left == NULL&&_root->_right == NULL)
        {
            if (count == k)
                return true;
            else
                return false;
        }
        return ((_IsBalance(_root->_left, count, k))&&(_IsBalance(_root->_right, count, k)));
    }
    void _Inorder(Node* Root)
    {
        if (Root)
        {
            _Inorder(Root->_left);
            cout << Root->_key << endl;
            _Inorder(Root->_right);
        }
    }
    Node* _Copy(Node* pRoot)
    {
        Node* pCur = pRoot;
        if (pCur)
        {
            pCur = new Node(pRoot->_key, pRoot->_value);
            pCur->_left= _Copy(pRoot->_left);
            pCur->_right = _Copy(pRoot->_right);
        }
        return pCur;
    }
    //销毁
    Node* _Destory(Node* pRoot)
    {
        if (pRoot)
        {
            pRoot->_left = _Destory(pRoot->_left);
            pRoot->_right = _Destory(pRoot->_right);
            delete pRoot;
            pRoot = NULL;
        }
        return pRoot;
    }
    Node* _root;
};

测试文件:

#include "RBtree.h"
using namespace std;
void test()
{
    RBTree<int, int> rb;
    int arr[] = { 10, 7, 8, 15, 5, 6, 11, 13, 12 };
    for (size_t idx = 0; idx < sizeof(arr) / sizeof(arr[0]); ++idx)
    {
        rb.Insert(arr[idx], idx);
    }
    rb.InOrder();
    if (rb.IsBalance())
        cout << "是红黑树." << endl;
    else
        cout << "不是红黑树." << endl;
    rb.InOrder();

}

int main()
{
    test();
    system("pause");
    return 0;
}

红黑树的应用

红黑树是一颗高效的二叉搜索树,用途很广,例如STL中set\map\unorder_map\unorder_set都运用到了红黑树。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是C++实现红黑树的算法代码: ```cpp #include <iostream> using namespace std; enum Color { RED, BLACK }; struct Node { int data; bool color; Node *left, *right, *parent; Node(int data) { this->data = data; left = right = parent = NULL; this->color = RED; } }; class RedBlackTree { private: Node *root; protected: void rotateLeft(Node *&); void rotateRight(Node *&); void fixViolation(Node *&); void inorderBST(Node *); public: RedBlackTree() { root = NULL; } void insert(const int &n); void inorder(); }; void RedBlackTree::rotateLeft(Node *&ptr) { Node *newPtr = ptr->right; ptr->right = newPtr->left; if (ptr->right != NULL) ptr->right->parent = ptr; newPtr->parent = ptr->parent; if (ptr->parent == NULL) root = newPtr; else if (ptr == ptr->parent->left) ptr->parent->left = newPtr; else ptr->parent->right = newPtr; newPtr->left = ptr; ptr->parent = newPtr; } void RedBlackTree::rotateRight(Node *&ptr) { Node *newPtr = ptr->left; ptr->left = newPtr->right; if (ptr->left != NULL) ptr->left->parent = ptr; newPtr->parent = ptr->parent; if (ptr->parent == NULL) root = newPtr; else if (ptr == ptr->parent->left) ptr->parent->left = newPtr; else ptr->parent->right = newPtr; newPtr->right = ptr; ptr->parent = newPtr; } void RedBlackTree::fixViolation(Node *&ptr) { Node *parentPtr = NULL; Node *grandParentPtr = NULL; while ((ptr != root) && (ptr->color != BLACK) && (ptr->parent->color == RED)) { parentPtr = ptr->parent; grandParentPtr = ptr->parent->parent; if (parentPtr == grandParentPtr->left) { Node *unclePtr = grandParentPtr->right; if (unclePtr != NULL && unclePtr->color == RED) { grandParentPtr->color = RED; parentPtr->color = BLACK; unclePtr->color = BLACK; ptr = grandParentPtr; } else { if (ptr == parentPtr->right) { rotateLeft(parentPtr); ptr = parentPtr; parentPtr = ptr->parent; } rotateRight(grandParentPtr); swap(parentPtr->color, grandParentPtr->color); ptr = parentPtr; } } else { Node *unclePtr = grandParentPtr->left; if ((unclePtr != NULL) && (unclePtr->color == RED)) { grandParentPtr->color = RED; parentPtr->color = BLACK; unclePtr->color = BLACK; ptr = grandParentPtr; } else { if (ptr == parentPtr->left) { rotateRight(parentPtr); ptr = parentPtr; parentPtr = ptr->parent; } rotateLeft(grandParentPtr); swap(parentPtr->color, grandParentPtr->color); ptr = parentPtr; } } } root->color = BLACK; } void RedBlackTree::insert(const int &data) { Node *ptr = new Node(data); root = ptr; fixViolation(ptr); } void RedBlackTree::inorderBST(Node *ptr) { if (ptr == NULL) return; inorderBST(ptr->left); cout << ptr->data << " "; inorderBST(ptr->right); } void RedBlackTree::inorder() { inorderBST(root); } int main() { RedBlackTree tree; tree.insert(7); tree.insert(6); tree.insert(5); tree.insert(4); tree.insert(3); tree.insert(2); tree.insert(1); cout << "Inorder Traversal of Created Tree\n"; tree.inorder(); return 0; } ``` 上面的代码实现红黑树的插入、旋转和修复违规的操作。其中,`rotateLeft`和`rotateRight`函数实现了左旋和右旋操作,`fixViolation`函数用于修复插入数据后可能会违反红黑树规则的情况,`insert`函数用于向红黑树中插入一个节点,`inorderBST`函数实现了中序遍历。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值