目录
红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路径会比其他路径长出俩倍,因而是接近平衡的。

1、每个结点不是红色就是黑色
2、根节点是黑色的
3、如果一个节点是红色的,则它的两个孩子结点是黑色的
4、对于每个结点,从该结点到其所有后代叶结点的简单路径上,均 包含相同数目的黑色结点
5、每个叶子结点都是黑色的(此处的叶子结点指的是空结点)
红黑树能够保证:其最长路径中节点个数不会超过最短路径节点个数的两倍。

最短路径为全黑,最长路径就是红黑节点交替(因为红色节点不能连续),每条路径的黑色节点相同,则最长路径、刚好是最短路径的两倍。
- // 节点的颜色
- enum Color { RED, BLACK };
- // 红黑树节点的定义
- template<class ValueType>
- struct RBTreeNode
- {
- RBTreeNode(const ValueType& data = ValueType(),Color color = RED)
- : _pLeft(nullptr), _pRight(nullptr), _pParent(nullptr)
- , _data(data), _color(color)
- {}
- RBTreeNode
* _pLeft; // 节点的左孩子 - RBTreeNode
* _pRight; // 节点的右孩子 - RBTreeNode
* _pParent; // 节点的双亲(红黑树需要旋转,为了实现简单给出该字段) - ValueType _data; // 节点的值域
- Color _color; // 节点的颜色
- };
红黑树是在二叉搜索树的基础上加上其平衡限制条件,因此红黑树的插入可分为两步:
1、按照二叉搜索树的规则插入新节点
- template<class ValueType>
- class RBTree
- {
- //……
- bool Insert(const ValueType& data)
- {
- PNode& pRoot = GetRoot();
- if (nullptr == pRoot)
- {
- pRoot = new Node(data, BLACK);
- // 根的双亲为头节点
- pRoot->_pParent = _pHead;
- _pHead->_pParent = pRoot;
- }
- else
- {
- // 1. 按照二叉搜索的树方式插入新节点
- // 2. 检测新节点插入后,红黑树的性质是否造到破坏,
- // 若满足直接退出,否则对红黑树进行旋转着色处理
- }
- // 根节点的颜色可能被修改,将其改回黑色
- pRoot->_color = BLACK;
- _pHead->_pLeft = LeftMost();
- _pHead->_pRight = RightMost();
- return true;
- }
- private:
- PNode& GetRoot() { return _pHead->_pParent; }
- // 获取红黑树中最小节点,即最左侧节点
- PNode LeftMost();
- // 获取红黑树中最大节点,即最右侧节点
- PNode RightMost();
- private:
- PNode _pHead;
- };
2、检测新节点插入后,红黑树的性质是否遭到破坏
因为新节点的默认颜色是红色,因此:如果其双亲节点的颜色是黑色,没有违反红黑树任何性质,则不需要调整;但当新插入节点的双亲节点颜色为红色时,就违反了性质三不能有连在一起的红色节点,此时需要对红黑树分情况来讨论:
约定:cur为当前节点,p为父节点,g为祖父节点,u为叔叔节点
情况一: cur为红,p为红,g为黑,u存在且为红

情况二: cur为红,p为红,g为黑,u不存在/u为黑

p为g的左孩子,cur为p的左孩子,则进行右单旋转;相反,
p为g的右孩子,cur为p的右孩子,则进行左单旋转
p、g变色--p变黑,g变红
情况三: cur为红,p为红,g为黑,u不存在/u为黑

p为g的左孩子,cur为p的右孩子,则针对p做左单旋转;相反,
p为g的右孩子,cur为p的左孩子,则针对p做右单旋转
则转换成了情况2
对每种情况进行相应的处理即可。
- bool Insert(const ValueType& data)
- {
- // ...
- // 新节点插入后,如果其双亲节点的颜色为空色,则违反性质3:不能有连在一起的红色结点
- while (pParent && RED == pParent->_color)
- {
- // 注意:grandFather一定存在
- // 因为pParent存在,且不是黑色节点,则pParent一定不是根,则其一定有双亲
- PNode grandFather = pParent->_pParent;
- // 先讨论左侧情况
- if (pParent == grandFather->_pLeft)
- {
- PNode unclue = grandFather->_pRight;
- // 情况三:叔叔节点存在,且为红
- if (unclue && RED == unclue->_color)
- {
- pParent->_color = BLACK;
- unclue->_color = BLACK;
- grandFather->_color = RED;
- pCur = grandFather;
- pParent = pCur->_pParent;
- }
- else
- {
- // 情况五:叔叔节点不存在,或者叔叔节点存在且为黑
- if (pCur == pParent->_pRight)
- {
- _RotateLeft(pParent);
- swap(pParent, pCur);
- }
- // 情况五最后转化成情况四
- grandFather->_color = RED;
- pParent->_color = BLACK;
- _RotateRight(grandFather);
- }
- }
- else
- {
-
- }
- }
- // ...
- }
红黑树的检测分为两步:
1、检测其是否满足二叉搜索树(中序遍历是否为有序序列)
2、检测其是否满足红黑树的性质
- bool IsValidRBTree()
- {
- PNode pRoot = GetRoot();
- // 空树也是红黑树
- if (nullptr == pRoot)
- return true;
- // 检测根节点是否满足情况
- if (BLACK != pRoot->_color)
- {
- cout << "违反红黑树性质二:根节点必须为黑色" << endl;
- return false;
- }
- // 获取任意一条路径中黑色节点的个数
- size_t blackCount = 0;
- PNode pCur = pRoot;
- while (pCur)
- {
- if (BLACK == pCur->_color)
- blackCount++;
- pCur = pCur->_pLeft;
- }
- // 检测是否满足红黑树的性质,k用来记录路径中黑色节点的个数
- size_t k = 0;
- return _IsValidRBTree(pRoot, k, blackCount);
- }
- bool _IsValidRBTree(PNode pRoot, size_t k, const size_t blackCount)
- {
- //走到null之后,判断k和black是否相等
- if (nullptr == pRoot)
- {
- if (k != blackCount)
- {
- cout << "违反性质四:每条路径中黑色节点的个数必须相同" << endl;
- return false;
- }
- return true;
- }
- // 统计黑色节点的个数
- if (BLACK == pRoot->_color)
- k++;
- // 检测当前节点与其双亲是否都为红色
- PNode pParent = pRoot->_pParent;
- if (pParent && RED == pParent->_color && RED == pRoot->_color)
- {
- cout << "违反性质三:没有连在一起的红色节点" << endl;
- return false;
- }
- return _IsValidRBTree(pRoot->_pLeft, k, blackCount) &&
- _IsValidRBTree(pRoot->_pRight, k, blackCount);
- }
此部分不做讲解,相比较插入,删除部分复杂一些。
红黑树和AVL树都是高效的平衡二叉树,增删改查的时间复杂度都是O(),红黑树不追求绝对平衡,其只需保证最长路径不超过最短路径的2倍,相对而言,降低了插入和旋转的次数,所以在经常进行增删的结构中性能比AVL树更优,而且红黑树实现比较简单,所以实际运用中红黑树更多。
迭代器的好处是可以方便遍历,是数据结构的底层实现与用户透明。
在迭代器部分比较难写的是重载++和--;
下面附上源码
RBTree.h
- #pragma once
- enum Color
- {
- RED = 0,
- BLACK
- };
- template <class T>
- struct RBTreeNode
- {
- typedef RBTreeNode
Node; - RBTreeNode
* _left; - RBTreeNode
* _right; - RBTreeNode
* _parent; - Color _col;
- T _data;
- RBTreeNode(const T data = T())
- :_left(nullptr),
- _right(nullptr),
- _parent(nullptr),
- _col(RED),
- _data(data)
- {}
- };
- template <class T,class Ref,class Ptr>
- struct RBTreeIterator
- {
- public:
- typedef RBTreeNode
Node; - typedef RBTreeIterator
Self; - RBTreeIterator(Node* ptr)
- :_Node(ptr)
- {}
- T& operator*()
- {
- return _Node->_data;
- }
- T* operator->()
- {
- return &(_Node->_data);
- }
- bool operator!=(Self it)
- {
- return _Node != it._Node;
- }
- bool operator==(Self it)
- {
- return _Node == it._Node;
- }
- Self& operator++()
- {
- Increament();
- return *this;
- }
- Self& operator--()
- {
- DeIncreament();
- return *this;
- }
-
- private:
- void Increament()
- {
- if (_Node->_right)
- {
- _Node = _Node->_right;
- //节点的右边存在,则在右边子树中找到最左边的那个节点
- while (_Node->_left)
- {
- _Node = _Node->_left;
- }
- }
- else
- {
- //节点的右边不存在,则向上找父亲
- Node* parent = _Node->_parent;
- while (parent && _Node == parent->_right)
- {
- _Node = parent;
- parent = _Node->_parent;
- }
- _Node = parent;
- }
- }
- void DeIncreament()
- {
- if (_Node->_left)
- {
- _Node = _Node->_left;
- while (_Node->_right)
- {
- _Node = _Node->_right;
- }
- }
- else
- {
- Node* parent = _Node->_parent;
- while (parent&& _Node == parent->_left)
- {
- _Node = parent;
- parent = _Node->_parent;
- }
- _Node = parent;
- }
- }
- Node* _Node;
- };
- template <class K,class T, class KeyOfValue>
- class RBTree
- {
- public:
- typedef RBTreeNode
Node; - typedef RBTreeIterator
Iterator; - typedef RBTreeIterator<const T, const T&, const T*> const_Iterator;
- RBTree()
- :_root(nullptr)
- {}
- RBTree(const RBTree
& RBT) - {
- _root = Copy(RBT._root);
- }
- Iterator begin()
- {
- Node* left = _root;
- while (left->_left)
- {
- left = left->_left;
- }
- return Iterator(left);
- }
- Iterator end()
- {
- return Iterator(nullptr);
- }
- pair
bool > Insert(const T data) - {
- if (_root == nullptr)
- {
- _root = new Node(data);
- _root->_col = BLACK;
- return make_pair(Iterator(_root), true);
- }
- //插入
- //首先找到要插入的位置
- Node* cur = _root;
- Node* parent = _root;
- while (cur)
- {
- if (kov(cur->_data) > kov(data))
- {
- parent = cur;
- cur = cur->_left;
- }
- else if (kov(cur->_data) < kov(data))
- {
- parent = cur;
- cur = cur->_right;
- }
- else//找到了相同的Key值
- {
- return make_pair(Iterator(cur), false);
- }
- }
- //连接parent和cur
- cur = new Node(data);
- Node* newnode = cur;
- cur->_col = RED;
- cur->_parent = parent;
- if (kov(data) > kov(parent->_data))
- {
- parent->_right = cur;
-
- }
- else if (kov(data) < kov(parent->_data))
- {
- parent->_left = cur;
- }
- //连接好了,开始修正
- //不能出现连续的红节点
- //一个红节点
- while (parent && parent->_col == RED)
- {
- Node* grandfather = parent->_parent;
- if (parent == grandfather->_left)
- {
- Node* uncle = grandfather->_right;
- if (uncle && uncle->_col == RED)//叔叔存在且为红
- {
- parent->_col = BLACK;
- uncle->_col = BLACK;
- grandfather->_col = RED;
- cur = grandfather;
- parent = cur->_parent;
- }
- else//叔叔不存在或为黑
- {
- if (cur == parent->_left)
- {
- //右单旋
- RotateR(grandfather);
- parent->_col = BLACK;
- grandfather->_col = RED;
- }
- else
- {
- //左右单旋
- RotateL(parent);
- RotateR(grandfather);
- cur->_col = BLACK;
- grandfather->_col = RED;
- }
- break;
- }
- }
- else
- {
- Node* uncle = grandfather->_left;
- if (uncle && uncle->_col == RED)//叔叔存在且为红
- {
- parent->_col = BLACK;
- uncle->_col = BLACK;
- grandfather->_col = RED;
- cur = grandfather;
- parent = cur->_parent;
- }
- else//叔叔不存在或为黑
- {
- if (cur == parent->_right)
- {
- //左单旋
- RotateL(grandfather);
- parent->_col = BLACK;
- grandfather->_col = RED;
- }
- else
- {
- //右左单旋
- RotateR(parent);
- RotateL(grandfather);
- cur->_col = BLACK;
- grandfather->_col = RED;
- }
- break;
- }
- }
- }
- _root->_col = BLACK;
- return make_pair(Iterator(newnode), true);
- }
- Iterator Find(const K& key)
- {
- Node* cur = _root;
- while (cur)
- {
- if (kov(cur->_data) > key)
- {
- cur = cur->_left;
- }
- else if (kov(cur->_data) < key)
- {
- cur = cur->_right;
- }
- else
- {
- return Iterator(cur);
- }
- }
- return nullptr;
- }
- Node* LeftMost()
- {
- Node* left = _root;
- while (left->_left)
- {
- left = left->_left;
- }
- return left;
- }
- Node* RightMost()
- {
- Node* right = _root;
- while (right->_right)
- {
- right = right->_right;
- }
- return right;
- }
- //void Inorder()
- //{
- // _Inorder(_root);
- //}
- bool IsBanlance()
- {
- if (_root && _root->_col == RED)
- {
- cout << "根节点不是黑色" << endl;
- return false;
- }
- int benchmark = 0;
- Node* left = _root;
- while (left)
- {
- if (left->_col == BLACK)
- {
- benchmark++;
- }
- left = left->_left;
- }
- int blacknum = 0;
- return _IsBanlance(_root, benchmark, blacknum);
- }
- int Height()
- {
- return _Height(_root);
- }
- Node*& GetRoot()
- {
- return _root;
- }
- private:
- Node* Copy(Node* root)
- {
- if (root == nullptr)
- {
- return nullptr;
- }
- Node* newnode = new Node(root->_data);
- newnode->_col = root->_col;
- newnode->_left = Copy(root->_left);
- newnode->_right = Copy(root->_right);
- if (newnode->_left)
- {
- newnode->_left->_parent = newnode;
- }
- if (newnode->_right)
- {
- newnode->_right->_parent = newnode;
- }
- return newnode;
- }
- int _Height(Node* root)
- {
- if (root == nullptr)
- {
- return 0;
- }
- int leftheight = _Height(root->_left);
- int rightheight = _Height(root->_right);
- return leftheight > rightheight ? leftheight + 1 : rightheight + 1;
- }
- bool _IsBanlance(Node* root, int benchmark, int blacknum)
- {
- //检查每条路径黑节点的个数是否一致
- //以及是否有连续的红节点
- if (root == nullptr)
- {
- if (blacknum != benchmark)
- {
- cout << "存在路径黑色节点的数量不相等" << endl;
- return false;
- }
- return true;
- }
- if (root->_col == RED && root->_parent->_col == RED)//之所以可以这样是因为根节点是黑
- {
- cout << "存在连续的红节点" << endl;
- }
- if (root->_col == BLACK)
- {
- blacknum++;
- }
- return _IsBanlance(root->_left, benchmark, blacknum) && _IsBanlance(root->_right, benchmark, blacknum);
- }
- //void _Inorder(Node* root)
- //{
- // if (root == nullptr)
- // {
- // return;
- // }
- // _Inorder(root->_left);
- // cout << kov(root->_data) << endl;
- // _Inorder(root->_right);
- //}
- void RotateR(Node* parent)
- {
- Node* subL = parent->_left;
- Node* subLR = subL->_right;
- if (subLR)
- {
- subLR->_parent = parent;
- }
- parent->_left = subLR;
- Node* Pparent = parent->_parent;
- subL->_right = parent;
- parent->_parent = subL;
- if (parent == _root)
- {
- _root = subL;
- subL->_parent = nullptr;
- }
- else
- {
- subL->_parent = Pparent;
- if (kov(parent->_data) > kov(Pparent->_data))
- {
- Pparent->_right = subL;
- }
- else
- {
- Pparent->_left = subL;
- }
- }
- }
- void RotateL(Node* parent)
- {
- Node* subR = parent->_right;
- Node* subRL = subR->_left;
- if (subRL)
- {
- subRL->_parent = parent;
- }
- parent->_right = subRL;
- Node* Pparent = parent->_parent;
- subR->_left = parent;
- parent->_parent = subR;
- if (parent == _root)
- {
- _root = subR;
- subR->_parent = nullptr;
- }
- else
- {
- subR->_parent = Pparent;
- if (kov(parent->_data) > kov(Pparent->_data))
- {
- Pparent->_right = subR;
- }
- else
- {
- Pparent->_left = subR;
- }
- }
- }
- Node* _root;
- KeyOfValue kov;
- };
Mymap.h
- #pragma once
- #include "RBTree.h"
- namespace myset_map
- {
- template<class K,class V>
- class map
- {
- public:
- struct MapOfKey
- {
- const K& operator()(const pair
& data) - {
- return data.first;
- }
- };
- typedef typename RBTree
, MapOfKey>::Iterator Iterator; - Iterator begin()
- {
- return _t.begin();
- }
- Iterator end()
- {
- return _t.end();
- }
- pair
bool > Insert(const pair& data) - {
- return _t.Insert(data);
- }
- Iterator Find(const K& data)
- {
- return _t.Find(data);
- }
- private:
- RBTree
, MapOfKey> _t; - };
- }
Myset.h
- #pragma once
- #include "RBTree.h"
- namespace myset_map
- {
- template<class K>
- class set
- {
- public:
- struct SetOfKey
- {
- const K& operator()(const K& key)
- {
- return key;
- }
- };
- typedef typename RBTree
::Iterator Iterator; - Iterator begin()
- {
- return _t.begin();
- }
- Iterator end()
- {
- return _t.end();
- }
- pair
bool > Insert(const K& data) - {
- return _t.Insert(data);
- }
- Iterator Find(const K& data)
- {
- return _t.Find(data);
- }
- private:
- RBTree
_t;//使用拷贝构造的时候,对于类里面的成员,系统会自己完成浅拷贝。 - //在一棵红黑树中,需要完成深拷贝。
- };
- }
test.cpp(程序的入口)
- #include
- using namespace std;
- #include "RBTree.h"
- #include "Myset.h"
- #include "Mymap.h"
- #include
- #include
- void test_myset()
- {
- myset_map::set<int> s;
- s.Insert(10);
- s.Insert(9);
- s.Insert(8);
- s.Insert(7);
- auto it = s.begin();
- while (it != s.end())
- {
- cout << *it << endl;
- ++it;
- }
- cout << *s.Find(7) << endl;
- myset_map::set<int> copys(s);
- for (auto e : copys)
- {
- cout << e << endl;
- }
- }
- void test_mymap()
- {
- myset_map::map<int,int> s;
- //myset_map::map
::MapOfKey kov; - //cout << kov(make_pair(10, 10)) << endl;
- srand(time(0));
- vector<int> v;
- int N = 1000;
- for (int i = 0; i < 100; i++)
- {
- //v.push_back(rand() % 100);
- v.push_back(i);
- }
- for (auto e : v)
- {
- s.Insert(make_pair(e, e));
- }
- auto it = s.begin();
- while (it != s.end())
- {
- cout << it->first << it->second << " ";
- ++it;
- }
- cout << endl;
- if (s.Find(7) != nullptr)
- {
- cout << s.Find(7)->first << endl;
- }
- myset_map::map<int,int> copys(s);
- auto its = copys.Find(99);
- cout << its->first << endl;
- //for (auto e : copys)
- //{
- // cout << e.first << e.second << " ";
- //}
- while (its != copys.begin())
- {
- cout << its->first << its->second << " ";
- --its;
- }
- }
- int main()
- {
- //test_myset();
- test_mymap();
- return 0;
- }