要求:熟悉红黑树概念,性质,以及插入的原理,并画图实现
红黑树是一棵二叉搜索树。它有颜色限制,只能是红色或者黑色。且在根节点到空节点的路径中,最长路径不超过最短路径的两倍,所以红黑树是接近平衡的。
注意
有的地方说NIL是叶子节点,其实NIL节点就是空节点。
结论
根据红黑树的性质,我们可以得到一个结论:最长路径不超过最短路径的两倍。所以红黑树是接近平衡。
(1)红黑树采用三叉链的存储结构。
(2)红黑树带有一个头节点,头节点的parent指向根节点,左孩子指向最左节点,右孩子指向最右节点。
代码
//颜色
enum color
{
RED,
BLACK
};
//节点
//T可以是key
template
struct RBTreeNode
{
T _data;
color _col;
RBTreeNode* _left;
RBTreeNode* _right;
RBTreeNode* _parent;
RBTreeNode(const T& data)
:_data(data)
, _col(RED)
, _left(nullptr)
, _right(nullptr)
, _parent(nullptr)
{}
};
//KeyOfT是仿函数,重载了(),返回key。
//为什么返回key,因为节点存放的可能是K,也可能是pair,而插入比较是K,所以就返回key。
template
class RBTree
{
typedef RBTreeNode Node;
public:
RBTree()
: _size(0)
{
_pHead = new Node(T());
_pHead->_left = _pHead;
_pHead->_right = _pHead;
_pHead->_parent = nullptr;
}
private:
Node* _pHead;
_size_t size;
}
问题
为什么将节点的默认颜色设置为红色?
一个新节点作为要插入的节点,不能是黑色节点。因为会影响其他路径的黑色节点,不能保证每条路径的黑色节点数目相同。而插入红色节点不影响其他路径,只影响当前路径。
(1)红黑树是二叉搜索树,满足二叉搜索树的性质。所以先将节点插入,再来考虑是否需要对节点进行调整。
(2)如果插入节点的父节点是黑色的,插入新节点就不破坏红黑树的结构。
(3)如果插入节点的父节点是红色的(其祖父节点一定是黑色的),就得考虑以下两种情况:
a. 父亲节点为红色节点,叔叔节点为红色节点
b. 父节点为红色节点,叔叔节点为空,或者叔叔节点为黑色节点
(3)总结:红黑树插入关键看uncle节点。当uncle存在且为红色,变色+向上调整;当uncle不存在或者存在且为黑色时,旋转+变色,旋转后路径就变短,接近平衡。
template
class RBTree
{
typedef RBTreeNode Node;
public:
//...
// 插入值为data的节点
// 返回值含义:iterator代表新插入节点的迭代器 bool:代表释放插入是够成功
pair Insert(const T& data)
{
KeyOfT kot;
//先插入,再调整颜色
if (_pHead->_parent == nullptr)
{
_pHead->_parent = new Node(data);
_pHead->_parent->_col = BLACK;
_pHead->_parent->_parent = _pHead;
return make_pair(iterator(_pHead->_parent), true);
}
Node* parent = nullptr;
Node* cur = _pHead->_parent;//根结点
while (cur)
{
if (kot(cur->_data) < kot(data))
{
parent = cur;
cur = cur->_right;
}
else if (kot(cur->_data) > kot(data))
{
parent = cur;
cur = cur->_left;
}
else
{
return make_pair(iterator(cur),false);
}
}
cur = new Node(data);
cur->_parent = parent;
cur->_col = RED;//默认设置为红色
if (kot(parent->_data) < kot(cur->_data))
{
parent->_right = cur;
}
else
{
parent->_left = cur;
}
//记录新插入节点,方便后面返回
Node* newnode = cur;
//若parent为黑节点,则不用调整
//若parent为红节点,则grandfather一定为黑节点,此时颜色的调整取决于uncle
//uncle为红节点,直接将p和u变黑,g变红,再将cur = g,继续判断
//uncle不存在或者为黑节点,旋转+颜色调整
while (parent!=_pHead && parent->_col == RED)
{
Node* grandfather = parent->_parent;
if (parent == grandfather->_left)
{
Node* uncle = grandfather->_right;
//uncle存在且为红色
if (uncle && uncle->_col == RED)
{
parent->_col = uncle->_col = BLACK;
grandfather->_col = RED;
cur = grandfather;//如果cur是根节点,根节点是红色,不用担心,出了循环会处理
parent = cur->_parent;
}
//uncle不存在或者存在且为黑色
else
{
//右旋g,将p变黑,g变红
if (cur == parent->_left)
{
// g
// p
//c
RotateR(grandfather);
grandfather->_col = RED;
parent->_col = BLACK;
}
//左旋p,右旋g
else
{
// g
// p
// c
RotateL(parent);
RotateR(grandfather);
cur->_col = BLACK;
grandfather->_col = RED;
}
break;
}
}
//parent在grandparent的右边
else
{
Node* uncle = grandfather->_left;
if (uncle && uncle->_col == RED)
{
parent->_col = uncle->_col = BLACK;
grandfather->_col = RED;
cur = grandfather;
parent = cur->_parent;
}
else
{
//左旋g,将g变红,p变黑
if (cur == parent->_right)
{
// g
// p
// c
RotateL(grandfather);
grandfather->_col = RED;
parent->_col = BLACK;
}
//先右旋p,再左旋g,将g变黑,c变红
else
{
// g
// p
// c
RotateR(parent);
RotateL(grandfather);
grandfather->_col = RED;
cur->_col = BLACK;
}
break;
}
}
}
_pHead->_parent->_col = BLACK;
//记得更新最大节点和最小节点
_pHead->_left = _LeftMost();//返回最左节点(最小节点)
_pHead->_right = _RightMost();//返回最右边节点(最大节点)
++_size;
return make_pair(iterator(newnode),true);
}
private:
void RotateL(Node* pParent)
{
Node* cur = pParent->_right;
Node* curleft = cur->_left;
pParent->_right = curleft;
if (curleft)
{
curleft->_parent = pParent;
}
cur->_left = pParent;
//不要忘记父节点的链接
Node* pparent = pParent->_parent;
pParent->_parent = cur;
//要考虑parent的parent是否存在
if (pparent != _pHead)
{
if (pparent->_left == pParent)
{
pparent->_left = cur;
}
else
{
pparent->_right = cur;
}
cur->_parent = pparent;
}
else
{
_pHead->_parent = cur;
cur->_parent = _pHead;
}
}
void RotateR(Node* pParent)
{
Node* cur = pParent->_left;
Node* curright = cur->_right;
pParent->_left = curright;
if (curright)
{
curright->_parent = pParent;
}
cur->_right = pParent;
Node* pparent = pParent->_parent;
pParent->_parent = cur;
if (pparent != _pHead)
{
if (pparent->_left == pParent)
{
pparent->_left = cur;
}
else
{
pparent->_right = cur;
}
cur->_parent = pparent;
}
else
{
_pHead->_parent = cur;
cur->_parent = _pHead;
}
}
Node* _LeftMost()
{
Node* cur = _pHead->_parent;
while (cur && cur->_left)
{
cur = cur->_left;
}
return cur;
}
Node* _RightMost()
{
Node* cur = _pHead->_parent;
while (cur->_right)
{
cur = cur->_right;
}
return cur;
}
}
template
struct RBTreeIterator
{
typedef RBTreeNode Node;
typedef RBTreeIterator Self;
RBTreeIterator(Node* pNode)
: _pNode(pNode)
{}
// 让迭代器具有类似指针的行为
T& operator*()
{
return _pNode->_data;
}
T* operator->()
{
return &_pNode->_data;
}
// 让迭代器可以移动:前置/后置++
Self& operator++()
{
Increament();
return *this;
}
Self operator++(int)
{
RBTreeIterator tmp(_pNode);
Increament();
return tmp;
}
// 然迭代器可以移动:前置/后置--
Self& operator--()
{
DeIncreament();
return *this;
}
Self operator--(int)
{
RBTreeIterator tmp(_pNode);
DeIncreament();
return tmp;
}
// 让迭代器可以比较
bool operator!=(const Self& s)const
{
return _pNode != s._pNode;
}
bool operator==(const Self& s)const
{
return _pNode == s._pNode;
}
private:
//增加
void Increament()
{
//如果_pNode的右子树存在,来到右子树的最左节点
if (_pNode->_right)
{
Node* leftmost = _pNode->_right;
while (leftmost->_left)
{
leftmost = leftmost->_left;
}
_pNode = leftmost;
}
else
{
//如果cur是parent的左孩子,那么parent就是下一个节点。
//如果cur是parent的右孩子,说明parent已经访问过了,继续往上调整。
Node* cur = _pNode;
Node* parent = _pNode->_parent;
//parent是头节点时,cur是根节点,此时循环停止
while (parent->_parent != cur && cur == parent->_right)
{
cur = parent;
parent = parent->_parent;
}
_pNode = parent;
}
}
//减少
void DeIncreament()
{
//注意如果_pNode是头节点的话,--操作,_pNode要指向最右节点
if (_pNode->_parent->_parent = _pNode)
{
_pNode = _pNode->_right;
}
//如果_pNode的左子树存在,来到左子树的最右节点
else if (_pNode->_left)
{
Node* rightmost = _pNode->_left;
while (rightmost->_right)
{
rightmost = rightmost->_right;
}
_pNode = rightmost;
}
else
{
//如果cur是parent的右孩子,那么parent就是下一个要访问的节点
//如果cur是parent的左孩子,说明parent已经访问过了,继续网上调整。
Node* cur = _pNode;
Node* parent = _pNode->_parent;
while (parent->_parent != cur && cur == parent->_left)
{
cur = parent;
parent = parent->_parent;
}
_pNode = parent;
}
}
Node* _pNode;
};
template
class RBTree
{
typedef RBTreeNode Node;
public:
typedef RBTreeIterator iterator;
//...
// Begin和End迭代器
iterator Begin()
{
return iterator(_pHead->_left);
}
iterator End()
{
return iterator(_pHead);
}
//....
}
template
class RBTree
{
//...
//判断是否是RBTree
//不能单纯通过最长路径不超过最短路径这一特点来判断是否是RBTree
//要通过RBTree的性质来判断
bool IsRBTree()
{
return IsRBTree(_pHead->_parent);
}
bool IsRBTree(Node* root)
{
if (root == nullptr)
{
return true;
}
//根节点不是红节点
if (root->_col == RED)
{
return false;
}
//不能有连续的红节点,每条路径上黑节点数目相同
int benchmark = 0;//记录一条路径上的黑节点作为基准值,然后比较每条路径的黑节点数目
Node* cur = root;
while (cur)
{
if (cur->_col == BLACK)
{
++benchmark;
}
cur = cur->_left;
}
return CheckColor(root, 0, benchmark);
}
bool CheckColor(Node* root, int blacknum, int benchmark)
{
if (root == nullptr)
{
//如果黑节点数目不等于基准值,说明黑节点数目不一致,返回false
if (blacknum != benchmark)
{
return false;
}
return true;
}
if (root->_col == BLACK)
{
++blacknum;
}
//检查有没有连续的红节点
else if (root->_col == RED)
{
if (root->_parent->_col == RED)
{
return false;
}
}
return CheckColor(root->_left, blacknum, benchmark) && CheckColor(root->_right, blacknum, benchmark);
}
}
template
class RBTree
{
typedef RBTreeNode Node;
public:
typedef RBTreeIterator iterator;
// 红黑树是否为红,是返回true,否则返回false
bool Empty()const
{
return _size == 0;
}
// 返回红黑树中有效节点的个数
size_t Size()const
{
return _size;
}
// 将红黑树中的有效节点删除,注意:删除的是有效节点,不删除头结点
void Clear()
{
_Destroy(_pHead->_parent);
}
// 在红黑树中查找data,存在赶回该节点对应的迭代器,否则返回End()
iterator Find(const T& data)
{
KeyOfT kot;
Node* cur = _pHead->_parent;
while (cur)
{
if (kot(cur->_data) < kot(data))
{
cur = cur->_right;
}
else if (kot(cur->_data) > kot(data))
{
cur = cur->_left;
}
else
{
return iterator(cur);
}
}
return iterator(_pHead);
}
//高度
int Height()
{
return Height(_pHead->_parent);
}
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;
}
private:
//...
void _Destroy(Node*& pRoot)
{
if (pRoot == nullptr)
{
return;
}
_Destroy(pRoot->_left);
_Destroy(pRoot->_right);
delete pRoot;
pRoot = nullptr;
}
//...
MyRBTree.h
#pragma once
#include
#include
#include
#include
using namespace std;
//颜色
enum color
{
RED,
BLACK
};
//节点
template
struct RBTreeNode
{
T _data;
color _col;
RBTreeNode* _left;
RBTreeNode* _right;
RBTreeNode* _parent;
RBTreeNode(const T& data)
:_data(data)
, _col(RED)
, _left(nullptr)
, _right(nullptr)
, _parent(nullptr)
{}
};
template
struct RBTreeIterator
{
typedef RBTreeNode Node;
typedef RBTreeIterator Self;
typedef RBTreeIterator iterator;
RBTreeIterator(const iterator& it)
{
_pNode = it._pNode;
}
RBTreeIterator(Node* pNode)
: _pNode(pNode)
{}
// 让迭代器具有类似指针的行为
Ref operator*()
{
return _pNode->_data;
}
Ptr operator->()
{
return &_pNode->_data;
}
// 让迭代器可以移动:前置/后置++
Self& operator++()
{
Increament();
return *this;
}
Self operator++(int)
{
RBTreeIterator tmp(_pNode);
Increament();
return tmp;
}
// 然迭代器可以移动:前置/后置--
Self& operator--()
{
DeIncreament();
return *this;
}
Self operator--(int)
{
RBTreeIterator tmp(_pNode);
DeIncreament();
return tmp;
}
// 让迭代器可以比较
bool operator!=(const Self& s)const
{
return _pNode != s._pNode;
}
bool operator==(const Self& s)const
{
return _pNode == s._pNode;
}
//增量
void Increament()
{
if (_pNode->_right)
{
Node* leftmost = _pNode->_right;
while (leftmost->_left)
{
leftmost = leftmost->_left;
}
_pNode = leftmost;
}
else
{
Node* cur = _pNode;
Node* parent = _pNode->_parent;
//parent是头节点时,cur是根节点,此时循环停止
while (parent->_parent != cur && cur == parent->_right)
{
cur = parent;
parent = parent->_parent;
}
_pNode = parent;
}
}
//减少量
void DeIncreament()
{
//注意如果_pNode是头节点的话,--操作,_pNode要指向最右节点
if (_pNode->_parent->_parent = _pNode)
{
_pNode = _pNode->_right;
}
else if (_pNode->_left)
{
Node* rightmost = _pNode->_left;
while (rightmost->_right)
{
rightmost = rightmost->_right;
}
_pNode = rightmost;
}
else
{
Node* cur = _pNode;
Node* parent = _pNode->_parent;
while (parent->_parent != cur && cur == parent->_left)
{
cur = parent;
parent = parent->_parent;
}
_pNode = parent;
}
}
Node* _pNode;
};
// K: 作为查找和删除等函数的参数类型,实际就是T中的key
// T: 可能是键值对
// 可能是一个key
// 不论节点中存储的是 || key, 都是按照key来进行比较的
// KeyOfValue: 提取data中的Key
template
class RBTree
{
typedef RBTreeNode Node;
public:
typedef RBTreeIterator iterator;
typedef RBTreeIterator const_iterator;
RBTree()
: _size(0)
{
_pHead = new Node(T());
_pHead->_left = _pHead;
_pHead->_right = _pHead;
_pHead->_parent = nullptr;
}
// Begin和End迭代器
iterator Begin()
{
return iterator(_pHead->_left);
}
iterator End()
{
return iterator(_pHead);
}
// const迭代器
const_iterator Begin()const
{
return const_iterator(_pHead->_left);
}
const_iterator End()const
{
return const_iterator(_pHead);
}
// 插入值为data的节点
// 返回值含义:iterator代表新插入节点 bool:代表释放插入成功
pair Insert(const T& data)
{
KeyOfT kot;
//先插入,再调整颜色
if (_pHead->_parent == nullptr)
{
_pHead->_parent = new Node(data);
_pHead->_parent->_col = BLACK;
_pHead->_parent->_parent = _pHead;
return make_pair(iterator(_pHead->_parent), true);
}
Node* parent = nullptr;
Node* cur = _pHead->_parent;//根结点
while (cur)
{
if (kot(cur->_data) < kot(data))
{
parent = cur;
cur = cur->_right;
}
else if (kot(cur->_data) > kot(data))
{
parent = cur;
cur = cur->_left;
}
else
{
return make_pair(iterator(cur),false);
}
}
cur = new Node(data);
cur->_parent = parent;
cur->_col = RED;//默认设置为红色
if (kot(parent->_data) < kot(cur->_data))
{
parent->_right = cur;
}
else
{
parent->_left = cur;
}
//方便后面返回新插入节点的迭代器
Node* newnode = cur;
//若parent为黑节点,则不用调整
//若parent为红节点,则grandfather一定为黑节点,此时颜色的调整取决于uncle
//uncle为红节点,直接将p和u变黑,g变红,再将cur = g,继续判断
//uncle不存在或者为黑节点,旋转+颜色调整
while (parent!=_pHead && parent->_col == RED)
{
Node* grandfather = parent->_parent;
if (parent == grandfather->_left)
{
Node* uncle = grandfather->_right;
//uncle存在且为红色
if (uncle && uncle->_col == RED)
{
parent->_col = uncle->_col = BLACK;
grandfather->_col = RED;
cur = grandfather;//如果根节点是红色,不用担心,出了循环会处理
parent = cur->_parent;
}
//uncle不存在或者存在且为黑色
else
{
//右旋g,将p变黑,g变红
if (cur == parent->_left)
{
// g
// p
//c
RotateR(grandfather);
grandfather->_col = RED;
parent->_col = BLACK;
}
//左旋p,右旋g
else
{
// g
// p
// c
RotateL(parent);
RotateR(grandfather);
cur->_col = BLACK;
grandfather->_col = RED;
}
break;
}
}
//parent在grandparent的右边
else
{
Node* uncle = grandfather->_left;
if (uncle && uncle->_col == RED)
{
parent->_col = uncle->_col = BLACK;
grandfather->_col = RED;
cur = grandfather;
parent = cur->_parent;
}
else
{
//左旋g,将g变红,p变黑
if (cur == parent->_right)
{
// g
// p
// c
RotateL(grandfather);
grandfather->_col = RED;
parent->_col = BLACK;
}
//先右旋p,再左旋g,将g变黑,c变红
else
{
// g
// p
// c
RotateR(parent);
RotateL(grandfather);
grandfather->_col = RED;
cur->_col = BLACK;
}
break;
}
}
}
_pHead->_parent->_col = BLACK;
//记得更新最大节点
_pHead->_left = _LeftMost();
_pHead->_right = _RightMost();
++_size;
return make_pair(iterator(newnode),true);
}
// 红黑树是否为红,是返回true,否则返回false
bool Empty()const
{
return _size == 0;
}
// 返回红黑树中有效节点的个数
size_t Size()const
{
return _size;
}
// 将红黑树中的有效节点删除,注意:删除的是有效节点,不删除头结点
void Clear()
{
_Destroy(_pHead->_parent);
}
// 在红黑树中查找data,存在赶回该节点对应的迭代器,否则返回End()
iterator Find(const T& data)
{
KeyOfT kot;
Node* cur = _pHead->_parent;
while (cur)
{
if (kot(cur->_data) < kot(data))
{
cur = cur->_right;
}
else if (kot(cur->_data) > kot(data))
{
cur = cur->_left;
}
else
{
return iterator(cur);
}
}
return iterator(_pHead);
}
private:
Node* _LeftMost()
{
Node* cur = _pHead->_parent;
while (cur && cur->_left)
{
cur = cur->_left;
}
return cur;
}
Node* _RightMost()
{
Node* cur = _pHead->_parent;
while (cur->_right)
{
cur = cur->_right;
}
return cur;
}
void _Destroy(Node*& pRoot)
{
if (pRoot == nullptr)
{
return;
}
_Destroy(pRoot->_left);
_Destroy(pRoot->_right);
delete pRoot;
pRoot = nullptr;
}
void RotateL(Node* pParent)
{
Node* cur = pParent->_right;
Node* curleft = cur->_left;
pParent->_right = curleft;
if (curleft)
{
curleft->_parent = pParent;
}
cur->_left = pParent;
//不要忘记父节点的链接
Node* pparent = pParent->_parent;
pParent->_parent = cur;
//要考虑parent的parent是否存在
if (pparent != _pHead)
{
if (pparent->_left == pParent)
{
pparent->_left = cur;
}
else
{
pparent->_right = cur;
}
cur->_parent = pparent;
}
else
{
_pHead->_parent = cur;
cur->_parent = _pHead;
}
}
void RotateR(Node* pParent)
{
Node* cur = pParent->_left;
Node* curright = cur->_right;
pParent->_left = curright;
if (curright)
{
curright->_parent = pParent;
}
cur->_right = pParent;
Node* pparent = pParent->_parent;
pParent->_parent = cur;
if (pparent != _pHead)
{
if (pparent->_left == pParent)
{
pparent->_left = cur;
}
else
{
pparent->_right = cur;
}
cur->_parent = pparent;
}
else
{
_pHead->_parent = cur;
cur->_parent = _pHead;
}
}
private:
Node* _pHead;
size_t _size;
};
MySet.h
#pragma once
#include"MyRBTree2.0.h"
namespace zn
{
template
class set
{
//直接返回key
struct SetKeyOfT
{
const K& operator()(const K& key)
{
return key;
}
};
public:
//编译器不知道iterator是类型还是静态成员记得+typename,告诉编译器这是类型
//set存储类型是K,K不能修改,所以set的普通迭代器实际上是const迭代器
typedef typename RBTree::const_iterator iterator;
typedef typename RBTree::const_iterator const_iterator;
//调用const迭代器,得用const修饰的this去调用
iterator begin()const
{
return _t.Begin();
}
iterator end()const
{
return _t.End();
}
//这里的iterator是const_iterator
pair insert(const K& key)
{
pair::iterator,bool> ret = _t.Insert(key);//RBTree的Insert返回的pair中的iterator是普通iterator
//需要将普通iterator转换成const_iterator
//这里是用普通迭代器去构造const迭代器,所以在迭代器中写一个构造
return pair(ret.first, ret.second);
}
private:
//因为map和set用的是同一个类模板,所以set还是要传三个模板参数
//第一个K是map的find等函数用来接收参数的参数类型,map不能从pair中提取K,所以只能传K,
//这也导致set也得传第一个K
//第二个K是set的存储类型
RBTree _t;
};
}
MyMap.h
#pragma once
#include"MyRBTree2.0.h"
namespace zn
{
template
class map
{
//用来返回pair中的key
struct MapKeyOfT
{
const K& operator()(const pair& kv)
{
return kv.first;
}
};
public:
//编译器不知道iterator是类型还是静态成员记得+typename,告诉编译器这是类型
//pair中的K不能修改,所以+const
typedef typename RBTree, MapKeyOfT>::iterator iterator;
typedef typename RBTree, MapKeyOfT>::const_iterator const_iterator;
iterator begin()
{
return _t.Begin();
}
iterator end()
{
return _t.End();
}
const_iterator begin()const
{
return _t.Begin();
}
const_iterator end()const
{
return _t.End();
}
pair insert(const pair& kv)
{
return _t.Insert(kv);
}
V& operator[](const K& key)
{
pair ret = insert(make_pair(key, V()));
return ret.first->second;
}
private:
RBTree, MapKeyOfT> _t;
};
}