红黑树

一:红黑树
红黑树是一颗二叉搜索树,它的每一个节点增加了一个存储位用来表示颜色,可以是Red也可以是Black,通过对任意一条根到叶子节点的颜色来约束,红黑树保证最长路径是最短路径的两倍,因此近似平衡;
红黑树的性质:
1:每个节点不是红色就是黑色
2:根节点是黑色
3:如果一个节点时红,则它两个子节点是黑色的(没有连续的红色)
4:对每个节点,从该节点到其后代的所有叶子节点的简单路径,均有相同数目的黑节点(每条路径的黑色节点色数目相同)
定义一个红黑树:

template <class K,class V>
struct RBTreeNode
{
    RBTreeNode<K, V> *_left;
    RBTreeNode<K, V> *_right;
    RBTreeNode<K, V> *_parent;
    K _key;
    V _value;
    color _color;

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

思考为什么满足上述约束条件,最长路径不超过黑色节点的两倍
这里写图片描述
假设最极端的情况下,最长路径和最短路径的节点都为黑色,在黑色节点的中间加上红色节点,且红色节点的个数和黑色节点的个数相等,那么此时最长路径就是最短路径的2倍;
二:插入分析:
ps:cur为当前节点,p为父亲节点,u为叔叔节点,g为祖父节点
第一种情况:
cur为红,p为红,g为黑,u存在且为红,
此时要进行变色处理,p,u变黑,g变红,然后把g给cur,向上调整;
这里写图片描述

三角表示为子树,可能存在也可能不存在;
第二种情况:
cur为红,p为红,g为黑,u不存在或者是存在且为黑;
p为g的左孩子,cur是p的左孩子,此时进行右单旋,p和g变色。p变黑,g变红;
此时要经过旋转;
1:右旋
这里写图片描述
2:左旋
cur是p的右孩子,p是g的右孩子,进行左单旋。变色p和g变色,p变黑,g变红;
这里写图片描述
第三种情况:
cur为红,p为红g为黑;
u不存在或者是存在且为黑
p是g的左孩子cur是p的右孩子,此时要进行双旋,对p进行左单旋,对g进行右单旋

这里写图片描述
双旋的具体过程和AVL树很像,只有少了平衡因子的更新,但是多了变色处理;
AVL树的旋转http://blog.csdn.net/f2016913/article/details/69367756
当p在左边的过程也是如此,分为u存在且为红,u不存在或者是存在且为黑,u不存在或者是存在且为黑,p是g的左孩子cur是p的右孩子
三:插入算法:

```
//插入
    bool _Insert(const K&key)
    {
        if (_root == NULL)
        {
            _root = new Node(key);
            _root->_color = BLACK;//根节点为黑
            return true;
        }
        Node*parent = NULL;
        Node*cur = _root;

        while (cur)
        {
            if (cur->_key < key)//右边
            {
                parent = cur;
                cur = cur->_right;
            }
            else if (cur->_key>key)//左边
            {
                parent = cur;
                cur = cur->_left;
            }
            else
            {
                return false;//插入值相等
            }
        }

        cur = new Node(key);
        if (parent->_key < key)//右边
        {
            parent->_right = cur;
            cur->_parent = parent;
        }
        else
        {
            parent->_left = cur;
            cur->_parent = parent;
        }
        //父亲存在,且颜色为红
        while (parent &&parent->_color == RED)
        {
            Node*grandparent = parent->_parent;//祖父一定存在
            if (parent == grandparent->_left)//父亲在左边
            {
                //叔叔存在且为红
                Node*uncle = grandparent->_right;
                if (uncle&&uncle->_color == RED)
                {
                    //父亲和叔叔的颜色变黑,祖父的颜色变红
                    parent->_color = uncle->_color = BLACK;
                    grandparent->_color = RED;

                    cur = grandparent;//可能为子树上调
                    parent =cur->_parent;
                }
                //叔叔不存在或者是存在且为黑
                else
                {
                    //旋转
                    if ( cur==parent->_right)
                    {
                        //双旋
                        _RotateL(parent);
                        swap(parent, cur);
                    }
                        //右单旋
                    _RotateR(grandparent);///
                    parent->_color = BLACK;
                    grandparent->_color = RED;
                    break ;
                }
            }
            //父亲在右边
            else//parent == grandparent->_right
            {
                //叔叔存在且为红
                Node*uncle = grandparent->_left;
                if (uncle&&uncle->_color == RED)
                {
                    //变色
                    parent->_color = uncle->_color = BLACK;
                    grandparent->_color = RED;
                    //上调
                    cur = grandparent;
                    parent =cur->_parent;
                }
                //叔叔不存在或者存在且为黑
                else
                {
                    //双旋
                    if (cur == parent->_left)
                    {
                        _RotateR(parent);
                        swap(parent, cur);
                    }
                    _RotateL(grandparent);//右旋
                    parent->_color = BLACK;
                    grandparent->_color = RED;
                    break;
                }
            }
        }
        _root->_color = BLACK;
        return true;
      }

四:判断一个红黑树是否平衡
红黑树的性质,要满足任何一个路径黑色节点的个数相等;我们可以分别统计每条黑色节点的个数,当相等时就//判断是不是红黑树
//判断是不是红黑树

 bool IsBalance()
    {
        if (_root == NULL)
        {
            return true;
        }
        if (_root->_color == RED)//根节点为红
        {
            return false;
        }
        //统计黑节点的个数
        int blacknum = 0;
        Node*left = _root;
        while (left)
        {
            if (left->_color == BLACK)
            {
                blacknum++;
            }
                left = left->_left;

        }
        int num = 0;//表示任意一条路径黑节点的个数
        return _IsBalance(_root, blacknum, num);
    }
    //判断是否为红黑树
    bool _IsBalance(Node*root, const int blacknum, int num)
    {
        if (root == NULL)//表示一条路径已经走完
        {
            if (num != blacknum)
            {
                cout << "黑色节点的个数不相等" << endl;
                return false;
            }
            else
            {
                return true;
            }
        }
        if (root->_color == BLACK)
        {
        ++num;
        }
        //相邻的红节点
        if((root->_color == RED)
        &&(root->_parent->_color == RED))
        {
            cout <<"存在连续的红节点"<< root->_key << endl;
            return false;
        }
        return _IsBalance(root->_left, blacknum, num)
            && _IsBalance(root->_right, blacknum, num);

    }

五:完整代码:

#pragma once
using namespace std;
enum  color
{
    RED,
    BLACK,
};
template <class K,class V>
struct RBTreeNode
{
    RBTreeNode<K, V> *_left;
    RBTreeNode<K, V> *_right;
    RBTreeNode<K, V> *_parent;
    K _key;
    V _value;
    color _color;

    RBTreeNode(const K&key, const V&value =0)
        :_left(NULL)
        , _right(NULL)
        , _parent(NULL)
        , _key(key)
        , _value(value)
        , _color(RED)
    {}
};
template<class K,class V>
class RBTree
{
    typedef RBTreeNode<K, V>Node;
public:
    RBTree()
        :_root(NULL)
    {}

    RBTree(const RBTree<K, V>&tree)
    {
        _Copy(tree._root);
    }

    RBTree<K, V>&operator =(RBTree<K, V> tree)
    {
        RBTree<K, V> tmp(tree._root);
        swap(tree._root, _root);
        return *this;
    }

    ~RBTree()
    {
        _Destroy(_root);
    }
    //中序
    void InOrder()
    {
        _InOrder(_root);
        cout << endl;
    }
    //插入
    void Insert(const K& key)
    {
        _Insert(key);
    }
    //判断是不是红黑树
    bool IsBalance()
    {
        if (_root == NULL)
        {
            return true;
        }
        if (_root->_color == RED)//根节点为红
        {
            return false;
        }
        //统计黑节点的个数
        int blacknum = 0;
        Node*left = _root;
        while (left)
        {
            if (left->_color == BLACK)
            {
                blacknum++;
            }
                left = left->_left;

        }
        int num = 0;//表示任意一条路径黑节点的个数
        return _IsBalance(_root, blacknum, num);//判断左路径是不是平衡
    }
    //判断是否为红黑树
    bool _IsBalance(Node*root, const int blacknum, int num)
    {
        if (root == NULL)//表示一条路径已经走完
        {
            if (num != blacknum)
            {
                cout << "黑色节点的个数不相等" << endl;
                return false;
            }
            else
            {
                return true;
            }
        }
        if (root->_color == BLACK)
        {
        ++num;
        }
        //相邻的红节点
        if((root->_color == RED)
        &&(root->_parent->_color == RED))
        {
            cout <<"存在连续的红节点"<< root->_key << endl;
            return false;
        }
        return _IsBalance(root->_left, blacknum, num)
            && _IsBalance(root->_right, blacknum, num);

    }
protected:
    //中序遍历
    void _InOrder(Node*root)
    {
        Node*cur = root;
        if (cur == NULL)
        {
            return;
        }
        _InOrder(cur->_left);
        cout << cur->_key << " ";
        _InOrder(cur->_right);
    }

    //拷贝
    void _Copy(Node*root)
    {
        Node*cur = root;
        Node*newNode = NULL;
        while (cur)
        {
            newNode = new Node(cur->_key);
            newNode->_left = _Copy(cur->_left);
            newNode->_right = _Copy(cur->_right);
        }
        return newNode;
    }
    //删除
    void _Destroy(Node*root)
    {
        if (root == NULL)
        {
            return;
        }
        Node*cur = root;
        while (cur)
        {
            _Destroy(cur->_left);
            _Destroy(cur->_right);
            delete cur;
            cur = NULL;
        }
    }
    //插入
    bool _Insert(const K&key)
    {
        if (_root == NULL)
        {
            _root = new Node(key);
            _root->_color = BLACK;//根节点为黑
            return true;
        }
        Node*parent = NULL;
        Node*cur = _root;

        while (cur)
        {
            if (cur->_key < key)//右边
            {
                parent = cur;
                cur = cur->_right;
            }
            else if (cur->_key>key)//左边
            {
                parent = cur;
                cur = cur->_left;
            }
            else
            {
                return false;//插入值相等
            }
        }

        cur = new Node(key);
        if (parent->_key < key)//右边
        {
            parent->_right = cur;
            cur->_parent = parent;
        }
        else
        {
            parent->_left = cur;
            cur->_parent = parent;
        }
        //父亲存在,且颜色为红
        while (parent &&parent->_color == RED)
        {
            Node*grandparent = parent->_parent;//祖父一定存在
            if (parent == grandparent->_left)//父亲在左边
            {
                //叔叔存在且为红
                Node*uncle = grandparent->_right;
                if (uncle&&uncle->_color == RED)
                {
                    //父亲和叔叔的颜色变黑,祖父的颜色变红
                    parent->_color = uncle->_color = BLACK;
                    grandparent->_color = RED;

                    cur = grandparent;//可能为子树上调
                    parent =cur->_parent;
                }
                //叔叔不存在或者是存在且为黑
                else
                {
                    //旋转
                    if ( cur==parent->_right)
                    {
                        //双旋
                        _RotateL(parent);
                        swap(parent, cur);
                    }
                        //右单旋
                    _RotateR(grandparent);///
                    parent->_color = BLACK;
                    grandparent->_color = RED;
                    break ;
                }
            }
            //父亲在右边
            else//parent == grandparent->_right
            {
                //叔叔存在且为红
                Node*uncle = grandparent->_left;
                if (uncle&&uncle->_color == RED)
                {
                    //变色
                    parent->_color = uncle->_color = BLACK;
                    grandparent->_color = RED;
                    //上调
                    cur = grandparent;
                    parent =cur->_parent;
                }
                //叔叔不存在或者存在且为黑
                else
                {
                    //双旋
                    if (cur == parent->_left)
                    {
                        _RotateR(parent);
                        swap(parent, cur);
                    }
                    _RotateL(grandparent);//右旋
                    parent->_color = BLACK;
                    grandparent->_color = RED;
                    break;
                }
            }
        }
        _root->_color = BLACK;
        return true;
    }

protected:
    //左旋
    void _RotateL(Node*parent)
    {
        Node*subR = parent->_right;
        Node*subRL = subR->_left;
        parent->_right = subRL;
        if (subRL)
        {
            subRL->_parent = parent;
        }
        subR->_left = parent;
        Node*ppnode = parent->_parent;
        parent->_parent = subR;

        if (ppnode == NULL)
        {
            _root = subR;
            subR->_parent = NULL;
        }
        else//祖父不为空
        {
            if (ppnode->_left == parent)
            {
                ppnode->_left = subR;
            }
            else
            {
                ppnode->_right = subR;
            }
            subR->_parent = ppnode;
        }
    }
    //右旋
    void _RotateR(Node*parent)
    {
        Node*subL = parent->_left;
        Node*subLR = subL->_right;
        parent->_left = subLR;
        if (subLR)
        {
            subLR->_parent = parent;
        }
        subL->_right = parent;
        Node*ppnode = parent->_parent;
        parent->_parent = subL;

        if (ppnode == NULL)
        {
            _root = subL;
            subL->_parent = NULL;
        }
        else
        {
            if (ppnode->_right== parent)
            {
                ppnode->_right = subL;
            }
            else
            {
                ppnode->_left = subL;
            }
            subL->_parent = ppnode;
        }
    }

protected:
    Node*_root;
};
void TestRBTree()
{
    RBTree<int, int> t;
    int a[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };
    for (int i = 0; i < sizeof(a)/sizeof(a[0]); ++i)
    {
        t.Insert(a[i]);
    }
    t.InOrder();
    cout << "IsBalance?"<<t.IsBalance() << endl;
}

.cpp文件

#include<iostream>
#include"RBTree.h"

using namespace std;
int main()
{
    TestRBTree();
    system("pause");
    return 0;
}

六:红黑树和AVL树的比较:
红黑树的优点,高效的二叉搜索树,
AVL树的时间复杂度是O(lgN);
红黑树的时间复杂度是O(2lgN);近似平衡;最长路径是最短路径的2倍,此时不用选装,而AVL树当左右字数的高度差的绝对值大于1要进行旋转,而且还要更新平衡因子;所以综合来看红黑树比AVL树高效;
红黑树的应用:
1. C++ STL库 – map
2. Java 库
3. linux内核
4. 其他一些库

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值