码迷,mamicode.com
首页 > 其他好文 > 详细

二叉搜索树—RBTree(红黑树)

时间:2016-07-20 06:47:25      阅读:118      评论:0      收藏:0      [点我收藏+]

标签:红黑树、rbtree、平衡搜索树


       红黑树又称二叉搜索树,它主要是通过红和黑两种颜色(red、black)来标识节点。通过对任何一条从根节点到叶子节点路径上的节点颜色进行约束,红黑树保证最长路径不超过最短路径的两倍,所以说:红黑树是近似于平衡的



■下面是红黑树的主要特点:

        (1)红黑树的根节点是黑色的。

        (2)红黑树中若一个节点是红色的,则它的两个子节点必须是黑色的。

        (3)红黑树中从该节点到后代叶节点的路径上,黑色节点数目是相同的。



       ◆红黑树的应用:

                 C++库、linux内核、java库等


       ◆红黑树与AVL树的区别:

                  红黑树和AVL树都是高效的平衡搜索树,时间复杂度都是O(lgN);

                  红黑树对平衡的要求不是特别高,它只需要满足最长路径不超过最短路径的两倍,所以性能相对较高。



■下面是红黑树中节点结构:

enum color      //枚举节点的两种颜色
{
     RED,
     BLACK,
};

template <class K, class V>
struct RBTreeNode
{
     color _col;
     RBTreeNode<K, V>* _left;
     RBTreeNode<K, V>* _right;
     RBTreeNode<K, V>* _parent;
     K _key;
     V _value;
     
     RBTreeNode(const K& key, const V& value)
          :_key(key)
          , _value(value)
          , _left(NULL)
          , _right(NULL)
          , _parent(NULL)
          , _col(RED)          //颜色必须插入的是红色,因为要保证黑色节点的个数是平衡的
     { }
};



■下面分析红黑树的插入情况:

(1)


技术分享




(2)


技术分享


(3)


技术分享


■下面是主要的代码:

#pragma once
//实现红黑树的基本功能
/*
1.红黑树中的节点只能是红色或者黑色
2.红黑树的根节点为黑色
3.红黑树的左、右子树的黑色节点个数是相同的
4.红黑树中红色节点的两个孩子节点必须都为黑色节点
*/

enum color      //枚举节点的两种颜色
{
     RED,
     BLACK,
};

template <class K, class V>
struct RBTreeNode
{
     color _col;
     RBTreeNode<K, V>* _left;
     RBTreeNode<K, V>* _right;
     RBTreeNode<K, V>* _parent;
     K _key;
     V _value;
     
     RBTreeNode(const K& key, const V& value)
          :_key(key)
          , _value(value)
          , _left(NULL)
          , _right(NULL)
          , _parent(NULL)
          , _col(RED)          //颜色必须插入的是红色,因为要保证黑色节点的个数是平衡的
     { }
};

template <class K, class V>
class RBTree
{
     typedef RBTreeNode<K, V> Node;
public:
     RBTree()
          :_root(NULL)
     {}
     
     bool Insert(const K& key, const V& value)
     {
          if (_root == NULL)      //根节点为空的情况,必须将根节点置为黑色
          {
               _root = new Node(key, value);
               _root->_col = BLACK;
               return true;
          }
          Node* cur = _root;
          Node* parent = NULL;
          while (cur)
          {
               if (cur->_key < key)
               {
                    parent = cur;
                    cur = cur->_right;
               }
               else if (cur->_key > key)
               {
                    parent = cur;
                    cur = cur->_left;
               }
               else
               {
                    break;
               }
          }
          
          //寻找到数据该插入的位置
          if (parent->_key < key)
          {
               Node* tmp = new Node(key, value);
               parent->_right = tmp;
               tmp->_parent = parent;
          }
          else if (parent->_key > key)
          {
               Node* tmp = new Node(key, value);
               parent->_left = tmp;
               tmp->_parent = parent;
          }
          
      //处理(如果父节点为黑色,则不用对树进行调整,树保持红黑树的状态)
          while(cur != _root && parent->_col == RED)
          //插入的不是根节点,且父节点的颜色为红
          {
               Node* grandFather = parent->_parent;
               if (parent == grandFather->_left)
               {
                    Node* uncle = grandFather->_right;
                    //情况一:需要将祖父节点置为红色,将父亲节点和叔叔节点置为黑色,
                    //下次直接从祖父节点向上进行调整
                    if (uncle != NULL && uncle->_col == RED)    
                    {
                     grandFather->_col = RED;
                     parent->_col = BLACK;
                     uncle->_col = BLACK;
                     cur = grandFather;
                     parent = cur->_parent;
                    }
                    else
                    {
                     //情况二:需要先进行右单旋,然后将父亲节点置为黑色,祖父节点置为红色
                      //情况三:需要先进行左单旋,然后就会转化为情况二
                     if (cur == parent->_right && parent->_right != NULL)  //情况三左、右
                     {
                      _RotateL(parent);
                     }
                     parent->_col = BLACK;     
                     grandFather->_col = RED;
                     _RotateR(grandFather);
                    
                    }
               }
               else     //父亲节点为祖父节点的右节点
               {
                    Node* uncle = grandFather->_left;
                    //情况一:需要将祖父节点置为红色,将父亲节点和叔叔节点置为黑色,
                    //下次直接从祖父节点向上进行调整
                    if (uncle != NULL && uncle->_col == RED)
                    {
                         grandFather->_col = RED;
                         parent->_col = BLACK;
                         uncle->_col = BLACK;
                         cur = grandFather;
                         parent = cur->_parent;
                    }
                    else
                    {
                     //情况二:需要先进行左单旋,然后将父亲节点置为黑色,祖父节点置为红色
                     //情况三:需要进行右单旋,然后就会转化为情况二
                         if (cur == parent->_left && parent->_left != NULL)//情况三右、左
                         {
                              _RotateR(parent);
                         }
                         parent->_col = BLACK;
                         grandFather->_col = RED;
                         _RotateL(grandFather);
                    }
               }
          }
          _root->_col = BLACK;
          return true;
     }

     void InOrder()
     {
          _InOrder(_root);
          cout << endl;
     }
     
     bool Check()     //检查是否为红黑树
     {
          int countBlack = 0;
          Node* cur = _root;
          while (cur->_left != NULL)    //统计一条路径上的黑色节点的数目
          {
               if (cur->_col == BLACK)
               {
                    countBlack++;
               }
               cur = cur->_left;
          }
          return _Check(_root, 0, countBlack);
     }
     
protected:
     bool _Check(Node* root, int blackNum, int curBalanceNum)
     {
          if (root == NULL)
          {
               return false;
          }
          if (root->_parent != NULL && root->_col == BLACK)   
          {
               if (root->_parent->_col == RED)
               {
                    return true;
               }
          }
          if (root->_left == NULL && root->_right == NULL)     //递归到叶子节点是的黑色节点数目是否相等
          {
               if (blackNum == curBalanceNum)
               {
                    return true;
               }
               else
               {
                    return false;
               }
          }
          return _Check(root->_left, blackNum++, curBalanceNum)
           && _Check(root->_right, blackNum++, curBalanceNum);
     }

     void _InOrder(Node* root)
     {
          if (root == NULL)
          {
               return;
          }
          _InOrder(root->_left);
          cout << root->_key <<":"<<root->_col<<endl;
          _InOrder(root->_right);
     }

     void _RotateL(Node*& parent)     //左单旋
     {
          Node* SubR = parent->_right;    //新建两个节点指针
          Node* SubRL = SubR->_left;
          parent->_right = SubRL;        //进行调整
          if (SubRL)
          {
               SubRL->_parent = parent;
          }
          SubR->_left = parent;
          SubR->_parent = parent->_parent;
          parent->_parent = SubR;
          parent = SubR;
          if (parent->_parent == NULL)     //parent为根节点的情况
          {
               _root = parent;
          }
          else                             //parent不为根节点
          {
               Node* ppNode = parent->_parent;
               if (ppNode->_key > parent->_key)
               {
                    ppNode->_left = parent;
               }
               else
               {
                    ppNode->_right = parent;
               }
          }
     }

     void _RotateR(Node*& parent)     //右单旋
     {
          Node* SubL = parent->_left;   //新建两个节点指针
          Node* SubLR = SubL->_right;
          parent->_left = SubLR;    //进行调整
          if (SubLR)
          {
               SubLR->_parent = parent;
          }
          SubL->_right = parent;
          SubL->_parent = parent->_parent;
          parent->_parent = SubL;
          parent = SubL;
          if (parent->_parent == NULL)     //parent为根节点的情况
          {
               _root = parent;
          }
          else                             //parent不为根节点
          {
               Node* ppNode = parent->_parent;
               if (ppNode->_key > parent->_key)
               {
                    ppNode->_left = parent;
               }
               else
               {
                    ppNode->_right = parent;
               }
          }
     }
     
protected:
     Node* _root;
};

void Test()
{
     RBTree<int, int> ht;
     ht.Insert(5, 1);
     ht.Insert(9, 1);
     ht.Insert(3, 1);
     ht.Insert(1, 1);
     ht.Insert(8, 1);
     ht.Insert(2, 1);
     ht.Insert(4, 1);
     ht.Insert(6, 1);
     ht.Insert(7, 1);
     
     ht.InOrder();
     cout<<ht.Check()<<endl;
}






本文出自 “无心的执着” 博客,请务必保留此出处http://10740590.blog.51cto.com/10730590/1827889

二叉搜索树—RBTree(红黑树)

标签:红黑树、rbtree、平衡搜索树

原文地址:http://10740590.blog.51cto.com/10730590/1827889

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!