红黑树

红黑树

概念

它是一个平衡树,查找效率为O(log2n),中序遍历时为有序序列。我只实现了unique_insert,对于equal_insert,stl是把键值相同的节点当做到该节点的右孩子。所以遍历muti_map时遍历一个键值对应的多个时值的时候,应该先find找到第一个K的位置,在调用count函数找到该K有多少个键值相同的节点。从第一个find返回第一个key位置的迭代器,然后每遍历一个节点,++先后移一次即可。

特性
  1. 每个节点,不是红色就是黑色
  2. 不能有连续俩个红色节点,即父子节点不能同为红色
  3. 根节点必须是黑色的
  4. 任意一条路径上的黑色节点数目都相同
  5. NULL节点颜色是黑色(这个可以忽略)
旋转分析
简称

p :parent
g :grandfather
u :uncle

场景1

Cur 为红 , p 为 红 , g 为黑 , u 存在且为红色。
则将 p,u 改为 黑色,然后 g 改为红色,上溯。
这里写图片描述
场景2
Cur 为红 , p为红 , u 不存在/存在且为黑色 , g 为黑
这里 Cur 和 p 且为同一边, 当同为左时,右旋,同为右时,左旋。
这里写图片描述

分析

这里就需要分析了,这里存在俩种情况。
1. U不存在,那么pCur肯定为新增节点,如果Cur是上溯得到的结果的话,那Cur子树中必然有黑色节点,那么肯定在Cur没上溯变为红色前,这棵树一定就不平衡了。
2. U存在,现在要发生旋转,那pCur肯定不是新增节点,如果是新增节点,直接Cur变黑色即可,那么现在要发生旋转,必然是Cur的红色是上溯得到的结果。并且如果U存在,根据每条路径黑色节点数目相同的性质,C肯定为黑色。根据俩个节点不能同时为红色,那么a,b必然同为红色。

场景3

Cur为红色,p为红色,g为黑色,u为黑色或者不存在,此时 p / cur 不在一条边上,这个时候需要发生双旋转,如果cur 在 p的右边 , p在 g 左边的话,发生左右双旋转。那么Cur在p的左边,p在 g 的右边,发生右左双旋转。
这个图就不画了,根据上面那个图看就行了

分析
  1. U不存在,必然是新增节点,因为如果是上溯节点的话,g的右子树没有黑色节点,那么必然之前就不是平衡的,所以必定是新增节点。
  2. U存在,那么必然是上溯节点。而且P的另一边必为黑色。
#include <iostream>
#include <vector>
using namespace std;
enum COLOR
{
    RED,
    BALCK
};
template<class K,class V>
struct  RBTreeNode
{
    RBTreeNode()
    :_key(0), _value(0), _Parent(NULL), _PLeft(NULL), _PRight(NULL), _color(RED)
    {}
    RBTreeNode(K key, V value,COLOR color=RED)
        :_key(key), _value(value), _Parent(NULL), _PRight(NULL), _PLeft(NULL), _color(color)
    {}
                                                                                           -K _key;
    V _value;
    RBTreeNode<K, V>*_Parent;
    RBTreeNode<K, V> *_PRight;
    RBTreeNode<K, V> * _PLeft;
    COLOR _color;
};
template<class K, class V, class Ref, class Pointer>
class RBTreeIterator
{
    typedef RBTreeNode<K, V> Node;
    typedef RBTreeIterator<K, V, Ref, Pointer> Self;
public:
    RBTreeIterator()
        : _pNode(NULL)
    {}

    RBTreeIterator(Node* pNode)
        : _pNode(pNode)
    {}

    RBTreeIterator(RBTreeIterator& it)
        : _pNode(it._pNode)
    {}

    Self& operator++()
    {
        _Increment();
        return *this;
    }
    Self operator++(int)
    {
        Node*temp = _pNode;
        _Increment();
        return RBTreeIterator(temp);
    }
    Self& operator--()
    {
        _Decrement();
    }
    Self operator--(int)
    {
        Node*temp = _pNode;
        _Increment()
        return RBTreeIterator(temp);
    }
    Ref operator*()
    {
        return _pNode->_key;
    }
    const Ref operator*()const
    {
        return _pNode->_key;
    }
    Pointer operator->()
    {
        return &(_pNode->_key);
    }
    const Pointer operator->()const
    {
        return &(_pNode->_key);
    }
    bool operator==(const Self& it)
    {
        return  _pNode == it._pNode;
    }
    bool operator!=(const Self& it)
    {
        return _pNode != it._pNode;
    }
protected:
    void _Increment()
    {
        if (_pNode)
        {
            Node*pCur = _pNode;
            if (pCur->_Parent == pCur&&pCur->_color == RED) return ; //处理End 
            if (pCur->_PRight)
            {
                pCur = pCur->_PRight;
                while (pCur->_PLeft) pCur = pCur->_PLeft;
            }
            else
            {
                Node*parent = pCur->_Parent;
                while (parent->_PRight == pCur)
                {
                    pCur = pCur->_Parent;
                    parent = parent->_Parent;
                }
                if (pCur->_PRight != parent)pCur = pCur->_Parent; //处理当根为最大时,这里pCur为End,为了不让它走回去设置了这一条件
            }
            _pNode = pCur;
        }
    }
    void _Decrement()
    {
        if (_pNode)
        {
            Node * pCur = _pNode;
            if (pCur->_PLeft)
            {
                pCur = pCur->_PLeft;
                while (pCur->_PRight)
                {
                    pCur = pCur->_PRight;
                }
            }
            else
            {
                Node*parent = pCur->_Parent;
                if (parent->_PLeft == pCur)
                {
                    pCur = pCur->_Parent;
                    parent = parent->_Parent;
                }
                pCur = pCur->_Parent; // 这里不加,是为了让 根为最小时当走到End,在走回最小节点
            }
            _PNode = pCur;
        }
    }
protected:
    Node* _pNode;
};

template<class K,class V>
class RBTree
{
    typedef RBTreeNode<K, V> Node;
public:
    typedef RBTreeIterator<K, V, K&, K*> Iterator;
public:
    RBTree(V arr[], size_t size)
        :_pHead(new RBTreeNode<K,V>())
    {
        for (size_t idx = 0; idx < size; ++idx)
        {
            _Insert(arr[idx], idx);
        }
        _pHead->_PLeft = Min();
        _pHead->_PRight = Max();
    }
    void InOrder()
    {
        cout << "InOrder: ";
        _InOrder(_GetRoot());
        cout << endl;
    }
    bool CheckRBTree()
    {
        Node*_Root = _pHead->_Parent;
        if (_Root == NULL||(_Root->_PLeft==NULL&&_Root->_PRight==NULL&&_Root->_color==BALCK))  return true;
        else
        {
            size_t k = 0;
            Node*pCur = _Root;
            while (pCur->_PLeft)
            {
                if (pCur->_color == BALCK) k++;
                if (pCur->_color == RED&&(pCur->_PLeft->_color==pCur->_color)) return false; // 先找一条路径上的黑色节点的数目
                pCur = pCur->_PLeft;
            }
            if (pCur->_color == BALCK) k++;
            return _CheckRBTree(_Root, 1, k);  //这个传1的原因是从跟节点开始,根的数目为1,也为了防止只有根节点的情况出现,只有根节点的话,这里对比的参照变量肯定为1,这里传0的话肯定是错的。
        }
    }
    Iterator Begin()
    {
        return _pHead->_PLeft;
    }
    Iterator End()
    {
        return _pHead;
    }
    bool Empty()const
    {
        return  Begin() == End();
    }
    size_t Size()const
    {
        return _size;
    }
protected:
    Node* &_GetRoot()
    {
        return _pHead->_Parent;
    }
    bool _CheckRBTree(Node* pRoot, size_t blackCoount, const size_t k)
    {
        bool flag = false, flag_2 = false;
        if (pRoot)
        {
            if (pRoot->_PLeft == NULL&&pRoot->_PRight == NULL)
            {                                                                    
                if (k == blackCoount)                
                    return true;
                else
                    return false;
            }
            if (pRoot->_PLeft)
            {
                if (pRoot->_PLeft->_color == BALCK)
                     blackCoount++;
                else if(pRoot->_PLeft->_color==pRoot->_color) 
                     return false;                                      
                flag=_CheckRBTree(pRoot->_pLeft, blackCoount, k);
            }
            if (pRoot->_PRight)
            {
                if (pRoot->_PRight->_color == BALCK)
                     blackCoount++;
                else if(pRoot->_PRight->_color==pRoot->_color) 
                     return false;               
                flag_2=_CheckRBTree(pRoot->_PRight, blackCoount, k);
            }
            return flag&&flag_2;
        }
        else
        {
            return true;
        }
    }
    void _InOrder(Node* pRoot)
    {
        if (pRoot)
        {
            _InOrder(pRoot->_PLeft);
            cout << pRoot->_key << " ";
            _InOrder(pRoot->_PRight);
        }
    }
    void _RotateL(Node*parent)
    {
        Node*_Root = _pHead->_Parent;
        Node * PSubR = parent->_PRight;
        Node * PSubRL = PSubR->_PLeft;
        Node * Pparent = parent->_Parent;
        if (PSubRL)
        {
            PSubRL->_Parent = parent;
        }
        parent->_PRight = PSubRL;
        parent->_Parent = PSubR;
        PSubR->_PLeft = parent;
        PSubR->_Parent = Pparent;
        if (Pparent == _pHead)
        {
            _pHead->_Parent = PSubR;
        }
        else
        {
            if (Pparent->_PLeft == parent)Pparent->_PLeft = PSubR;
            else Pparent->_PRight = PSubR;
        }
    }
    void _RotateR(Node*parent)
    {
        Node*_Root = _pHead->_Parent;
        Node*PSubL = parent->_PLeft;
        Node*PSubLR = PSubL->_PRight;
        Node*Pparent = parent->_Parent;
        if (PSubLR)
        {
            PSubLR->_Parent = parent;
        }
        parent->_PLeft = PSubLR;
        parent->_Parent = PSubL;
        PSubL->_PRight = parent;
        PSubL->_Parent = Pparent;
        if (Pparent == _pHead)
        {
            _pHead->_Parent = PSubL;
        }
        else
        {
            if (Pparent->_PLeft == parent)Pparent->_PLeft = PSubL;
            else Pparent->_PRight = PSubL;
        }
    }
    bool _Insert(K key, V value)
    {
        Node * _Root = _pHead->_Parent;
        if (NULL==_Root)
        {
            _Root = new Node(key, value);
            _Root->_color = BALCK;
            _Root->_Parent = _pHead;
            _pHead->_Parent = _Root;
            _pHead->_PLeft = _Root;
            _pHead->_PRight = _Root;
            _size++;
            return true;
        }
        else
        {
            Node*pCur = _Root;
            Node*Parent = NULL;
            while (pCur)
            {
                if (key < pCur->_key)
                {
                    Parent = pCur;
                    pCur = pCur->_PLeft;
                }
                else if (key>pCur->_key)
                {
                    Parent = pCur;
                    pCur = pCur->_PRight;
                }
                else
                {
                    return false;
                }
            }
            pCur = new Node(key, value);
            if (key < Parent->_key)
            {
                Parent->_PLeft = pCur;
                pCur->_Parent = Parent;
            }
            else
            {
                Parent->_PRight = pCur;
                pCur->_Parent = Parent;
            }
            if (Parent->_color == BALCK)
            {
                _size++;
                return true;
            }
            else
            {
                Node* grandfather = NULL;
                Node* uncle = NULL;
                while (_Root != Parent&& Parent != _pHead) // 原来 _Root != Parent&& Parent != NULL  ,现在加入了_pHead 把判断为空的地方换成pHead即可
                {
                    grandfather = Parent->_Parent;
                    if (grandfather->_PLeft == Parent) uncle = grandfather->_PRight;
                    else uncle = grandfather->_PLeft;
                    if (uncle&&uncle->_color == RED)
                    {
                        uncle->_color = BALCK;
                        Parent->_color = BALCK;
                        grandfather->_color = RED;
                        pCur = grandfather;
                        Parent = grandfather->_Parent;
                    }
                    else if (Parent==grandfather->_PLeft)
                    {
                        if (pCur == Parent->_PRight)
                        {
                            _RotateL(Parent);
                            swap(Parent, pCur);
                        }
                        _RotateR(grandfather);
                        Parent->_color= BALCK;
                        grandfather->_color = RED;
                        _size++;
                        return true;
                    }
                    else if (Parent == grandfather->_PRight)
                    {
                        if (pCur == Parent->_PLeft)
                        {
                            _RotateR(Parent);
                            swap(Parent, pCur);
                        }
                        _RotateL(grandfather);
                        Parent ->_color= BALCK;
                        grandfather->_color = RED;
                        _size++;
                        return true;
                    }
                }
                _Root->_color = BALCK;
                _size++;
                return true;
            }
        }
    }
    Node *Min()
    {
        Node*_Root = _pHead->_Parent;
        Node*pCur = _Root;
        if (pCur)
        {
            while (pCur->_PLeft) pCur = pCur->_PLeft;
            return pCur;
        }
        else return NULL;
    }
    Node *Max()
    {
        Node*_Root = _pHead->_Parent;
        Node*pCur = _Root;
        if (pCur)
        {
            while (pCur->_PRight) pCur = pCur->_PRight;
            return pCur;
        }
        else return NULL;
    }
    private:
    //Node * _Root;
    Node * _pHead;
    size_t _size;
};

void TestRBTree()
{
    int a[] = { 10, 7, 8, 15, 5, 6, 11, 13, 12 };
    RBTree<int, int> t(a,sizeof(a)/sizeof(a[0]));

    t.InOrder();
    if (t.CheckRBTree())
    {
        cout << "是红黑树" << endl;
    }
    else
    {
        cout << "不是红黑树" << endl;
    }
}

判断红黑树是否平衡

        bool CheckRBTree()
    {
        Node*_Root = _pHead->_Parent;
        if (_Root == NULL||(_Root->_PLeft==NULL&&_Root->_PRight==NULL&&_Root->_color==BALCK))  return true;
        else
        {
            size_t k = 0;
            Node*pCur = _Root;
            while (pCur->_PLeft)
            {
                if (pCur->_color == BALCK) k++;
                if (pCur->_color == RED&&(pCur->_PLeft->_color==pCur->_color)) return false; // 先找一条路径上的黑色节点的数目
                pCur = pCur->_PLeft;
            }
            if (pCur->_color == BALCK) k++;
            return _CheckRBTree(_Root, 1, k);  //这个传1的原因是从跟节点开始,根的数目为1,也为了防止只有根节点的情况出现,只有根节点的话,这里对比的参照变量肯定为1,这里传0的话肯定是错的。
        }
    }
    bool _CheckRBTree(Node* pRoot, size_t blackCoount, const size_t k)
    {
        bool flag = false, flag_2 = false;
        if (pRoot)
        {
            if (pRoot->_PLeft == NULL&&pRoot->_PRight == NULL)
            {                                                                    
                if (k == blackCoount)                
                    return true;
                else
                    return false;
            }
            if (pRoot->_PLeft)
            {
                if (pRoot->_PLeft->_color == BALCK)
                     blackCoount++;
                else if(pRoot->_PLeft->_color==pRoot->_color) 
                     return false;                                      
                flag=_CheckRBTree(pRoot->_pLeft, blackCoount, k);
            }
            if (pRoot->_PRight)
            {
                if (pRoot->_PRight->_color == BALCK)
                     blackCoount++;
                else if(pRoot->_PRight->_color==pRoot->_color) 
                     return false;               
                flag_2=_CheckRBTree(pRoot->_PRight, blackCoount, k);
            }
            return flag&&flag_2;
        }
        else
        {
            return true;
        }
    }
map

  set与map就是使用红黑树进行了封装,map的value是pair < key,value> ,它的key 使用了仿函数KeyofValue返回得到的key,红黑树只保存了map的value也就是pair键值对
  说起来pair键值对,有俩个构造方法,第一个是make_pair,第二个是pair< T1,T2> (t1,t2)直接用pair构造函数来生成。但是它们俩个当中pair直接构造的方式的效率更高。从下面的代码中看到 make_pair比正常直接使用pair构造函数多了一次拷贝构造。

 1 // TEMPLATE STRUCT pair
 2 template<class _Ty1,class _Ty2> struct pair
 3 {   // store a pair of values
 4     typedef pair<_Ty1, _Ty2> _Myt;
 5     typedef _Ty1 first_type;
 6     typedef _Ty2 second_type;
 7 
 8     pair(): first(_Ty1()), second(_Ty2())
 9         {    // construct from defaults
10         }
11 
12     pair(const _Ty1& _Val1, const _Ty2& _Val2): first(_Val1), second(_Val2)
13         {    // construct from specified values
14         }
15 
16     template<class _Other1,
17         class _Other2>
18         pair(const pair<_Other1, _Other2>& _Right)
19         : first(_Right.first), second(_Right.second)
20         {    // construct from compatible pair
21         }
22 
23     void swap(_Myt& _Right)
24         {    // exchange contents with _Right
25         std::swap(first, _Right.first);
26         std::swap(second, _Right.second);
27         }
28 
29     _Ty1 first;    // the first stored value
30     _Ty2 second;    // the second stored value
31     };
32 
33 
34 template<class _Ty1,class _Ty2> inline
35     pair<_Ty1, _Ty2> make_pair(_Ty1 _Val1, _Ty2 _Val2)
36     {    // return pair composed from arguments
37     return (pair<_Ty1, _Ty2>(_Val1, _Val2));
38     }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值