【數據結構】紅黑樹

一、紅黑樹
紅黑樹是一棵二叉搜索樹,它在每個節點上增加了一個存儲位來表示結點的顏色,可以是 red 或者 black ,通過對任何一條從根節點到葉子節點簡單路徑上的顏色來約束,紅黑樹保證最長路徑不超過最短路徑的兩倍,因而近似平衡,而且在實際應用中發現紅黑樹性能確實比 AVL 樹 性能高。
AVL樹實現代碼: https://blog.csdn.net/lz201788/article/details/79451815

二、性質
1.每個節點不是紅色就是黑色
2.樹的根節點是黑色的
3.如果一個節點是紅色的,則它的兩個孩子節點是黑色的(沒有兩個連續的紅色節點)
4.對於每個節點,從該節點到其所有後代葉節點的簡單路徑上,均包含相同數目的黑色節點(每條路徑上黑色節點的數量相等)

三、插入實現

【情況一】
若樹爲空,插入後違反性質2,需要將新增節點改成黑色。

【情況二】
插入節點的父親節點爲黑色,不違反任何性質,直接插入。

約定:cur爲當前節點,p爲父親節點,g爲祖父節點,u爲叔叔節點
【情況三】
這裏寫圖片描述

【情況四】
這裏寫圖片描述

【情況五】
這裏寫圖片描述
【代碼實現】
【RBTree.h】

#pragma once
#include<iostream>
using namespace std;

enum Color
{
    RED,
    BLACK
};
template<class K,class V>
struct RBNode
{
    RBNode()
    :_Lchild(NULL)
    ,_Rchild(NULL)
    ,_Parent(NULL)
    , _color(RED)
    { }
    RBNode(K key,V value,Color color=RED)
        :_Lchild(NULL)
        , _Rchild(NULL)
        , _Parent(NULL)
        , _key(key)
        , _value(value)
        , _color(color)
    { }
    RBNode<K, V>* _Lchild;
    RBNode<K, V>* _Rchild;
    RBNode<K, V>* _Parent;
    K _key;
    V _value;
    Color _color;
};

template<class K, class V>
class RBTree
{
    typedef RBNode<K, V> Node;
    typedef RBNode<K, V>* pNode;
public:
    RBTree()
    {
        Root = NULL;
    }
    bool Insert(K k,V v)
    {
        return _Insert(Root,k,v);
    }
    void InOrder()
    {
        _InOrder(Root);
    }
    bool CheckRBT()
    {
        int blackcount = 0;
        int k = 0;
        pNode cur = Root;
        while (cur)
        {
            if (cur->_color == BLACK)
                blackcount++;
            cur = cur->_Lchild;
        }
        return _CheckRBT(Root,blackcount,k);
    }
private:
    bool _CheckRBT(pNode pRoot,int blackcount,int k)
    {
        if (pRoot == NULL)
        {
            if (blackcount == k)
                return true;
            else
                return false;
        }
        if (pRoot->_color == RED&&pRoot->_Parent->_color == RED)
            return false;
        if (pRoot->_color == BLACK)
            k++;
        return _CheckRBT(pRoot->_Lchild,blackcount,k);
        return _CheckRBT(pRoot->_Rchild, blackcount, k);

    }
    void _InOrder(pNode pRoot)
    {
        if (pRoot)
        {
            _InOrder(pRoot->_Lchild);
            cout << "<" << pRoot->_key << "," << pRoot->_value << ">" << endl;
            _InOrder(pRoot->_Rchild);
        }
    }
    bool _Insert(pNode& pRoot,K k,V v)
    {
        pNode newNode = new Node(k, v);
        if (pRoot == NULL)          //情況一
        {
            pRoot = newNode;
            newNode->_color = BLACK;
        }
        pNode cur = pRoot;
        pNode pParent = NULL;
        while (cur)                 
        {                           //查找要插入的位置
            pParent = cur;
            if (cur->_key > k)
                cur = cur->_Lchild;
            else if (cur->_key < k)
                cur = cur->_Rchild;
            else
                return false;     //k已存在
        }
        if (pParent->_key>k)
        {
            pParent->_Lchild = newNode;
            newNode->_Parent = pParent;
        }
        else
        {
            pParent->_Rchild = newNode;
            newNode->_Parent = pParent;
        }
        cur = newNode;

        pNode u = NULL;
        pNode p = pParent;
        while (cur!=Root&&p->_color==RED)
        {
            pNode g = p->_Parent;
            if (p== g->_Lchild)
                u = g->_Rchild;
            else
                u = g->_Lchild;

            if (p->_color == BLACK)        //情況二
                return true;
            else if (cur->_color==RED&&u->_color==RED)   //情況三
            {
                p->_color = BLACK;
                u->_color = BLACK;
                if (g!=Root)
                g->_color = RED;

                cur = g;
                p = cur->_Parent;
            }
            else if (cur->_color == RED&&g->_color == BLACK&&(u->_color==BLACK||u==NULL))   //情況四
            {
                p->_color = BLACK;
                g->_color = RED;
                if (cur == p->_Lchild&&p == g->_Lchild)
                {
                    //右單旋
                    RotateRight(g);
                }
                else if (cur == p->_Rchild&&p == g->_Rchild)
                {
                    //左單旋
                    RotateLeft(g);
                }
            }
            else if (cur->_color == RED&&g->_color == BLACK && (u->_color == BLACK || u == NULL))
            {
                if (p == g->_Lchild&&cur == p->_Rchild)
                {
                    //左單旋
                    RotateLeft(p);
                    swap(cur, p);
                }
                else if (p == g->_Rchild&&cur == p->_Lchild)
                {
                    //右單旋
                    RotateRight(p);
                    swap(cur, p);
                }
            }
            if (g == Root)
                g->_color = BLACK;
        }
        return true;
    }
    void RotateLeft(pNode g)
    {
        pNode pSubR = g->_Rchild;
        pNode pSubRL = pSubR->_Lchild;
        pNode pParent = g->_Parent;

        g->_Rchild = pSubRL;
        if (pSubRL != NULL)
            pSubRL->_Parent = g;
        pSubR->_Lchild = g;
        g->_Parent = pSubR;
        if (pParent == NULL)
            Root = pSubR;
        else if (pParent != NULL&&g == pParent->_Lchild)
        {
            pParent->_Lchild = g;
            g->_Parent = pParent;
        }
        else if (pParent != NULL&&g == pParent->_Rchild)
        {
            pParent->_Rchild = g;
            g->_Parent = pParent;
        }
    }
    void RotateRight(pNode g)
    {
        pNode pSubL = g->_Lchild;
        pNode pSubLR = pSubL->_Rchild;
        pNode pParent = g->_Parent;

        g->_Lchild = pSubLR;
        if (pSubLR)
            pSubLR->_Parent = g;
        pSubL->_Rchild = g;
        g->_Parent = pSubL;
        if (pParent == NULL)
            Root = pSubL;
        else if (pParent != NULL&&g == pParent->_Lchild)
        {
            pParent->_Lchild = pSubL;
            pSubL->_Parent = pParent;
        }
        else if (pParent != NULL&&g == pParent->_Rchild)
        {
            pParent->_Rchild = pSubL;
            pSubL->_Parent = pParent;
        }

    }

private:
    pNode Root;
};
//【測試函數】
void Test()
{
    RBTree<int, int> t;
    int arr[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };
    int size = sizeof(arr) / sizeof(arr[0]);
    for (int i = 0; i < size; i++)
    {
        t.Insert(arr[i], i);
    }
    t.InOrder();
    if (t.CheckRBT() == true)
        cout << "是紅黑樹" << endl;
    else
        cout << "不是紅黑樹" << endl;
}

【test.cpp】

#include"RBTree.h"

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

【刪除】:(參考下面的博客)
http://www.cnblogs.com/fornever/archive/2011/12/02/2270692.html
https://blog.csdn.net/chenhuajie123/article/details/11951777

發佈了70 篇原創文章 · 獲贊 92 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章