实践意义
在各方面,红黑树要比AVL树性能更好,用途也更广泛
map&set底层都主要靠红黑树
概念
性质
插入时,抽象图
cur为新插入
插入时颜色更新逻辑图
插入/旋转
插入时旋转操作同AVL树, 不同点即不用修改平衡因子, 但需要改变节点颜色, 具体可见文末代码
AVL/红黑树旋转方法:AVL解析-CSDN博客
板书
手动实现源代码
#include <iostream>
#include <assert.h>
using namespace std;
enum COLOUR
{
RED,
BLACK
};
template<class T>
struct RBTreeNode
{
RBTreeNode(const T& data = T())
: _pLeft(nullptr)
, _pRight(nullptr)
, _pParent(nullptr)
, _colour(RED)
, _data(data)
{; }
RBTreeNode<T>* _pLeft;
RBTreeNode<T>* _pRight;
RBTreeNode<T>* _pParent;
COLOUR _colour = RED;
T _data;
};
// 请模拟实现红黑树的插入--注意:为了后序封装map和set,本文在实现时给红黑树多增加了一个头结点
template<class T>
class RBTree
{
typedef RBTreeNode<T> Node;
public:
RBTree()
{
_pRoot = nullptr;
}
void Inorder()
{
_Inorder(_pRoot);
}
// 在红黑树中插入值为data的节点,插入成功返回true,否则返回false
// 注意:为了简单起见,本次实现红黑树不存储重复性元素
bool Insert(const T& data)
{
if (_pRoot == nullptr)
{
_pRoot = new Node(data);
_pRoot->_colour = BLACK;
return true;
}
//_pRoot不为空
Node* cur = _pRoot, * parent = nullptr;
while (cur)
{
if (cur->_data == data)//重复data
{
return false;
}
//data不重复
if (data > cur->_data)//cur右走
{
parent = cur;
cur = cur->_pRight;
}
else//cur往左走
{
parent = cur;
cur = cur->_pLeft;
}
}
cur = new Node(data);
if (data < parent->_data)//cur 在 parent 左
{
parent->_pLeft = cur;
cur->_pParent = parent;
}
else//cur在 右
{
parent->_pRight = cur;
cur->_pParent = parent;
}
//更新整个树的_colour
while (cur)//只有parent为黑或旋转后才可break
{
if (cur == _pRoot)
{
cur->_colour == BLACK;
break;
}
Node* parent = cur->_pParent;
if (parent->_colour == BLACK)
{
break;
}
//parent为红 , 必有grand
Node* grand = parent->_pParent;
Node* uncle = grand->_pRight;
if (parent == grand->_pRight) uncle = grand->_pLeft;
//以下主要看 uncle的color, 决定变色/旋转
if (uncle && uncle->_colour == RED)//变色即可
{
uncle->_colour = BLACK;
parent->_colour = BLACK;
grand->_colour = RED;
cur = grand;//继续向上更新, 不break
if (cur == _pRoot)
{
cur->_colour == BLACK;
break;
}
continue;
}
else //uncle为黑或unclue不存在, 旋转
{
if (parent == grand->_pLeft)
{
if (cur == parent->_pLeft)//右单旋
{
RotateR(grand);
parent->_colour = BLACK;
grand->_colour = cur->_colour = RED;
}
else//左右双旋
{
RotateLR(grand);
cur->_colour = BLACK;
parent->_colour = grand->_colour = RED;
}
}
else
{
if (cur == parent->_pRight)//左单旋
{
RotateL(grand);
parent->_colour = BLACK;
grand->_colour = cur->_colour = RED;
}
else//右左单旋
{
RotateRL(grand);
cur->_colour = BLACK;
parent->_colour = grand->_colour = RED;
}
}
break;
}
}
_pRoot->_colour = BLACK;
}
// 检测红黑树中是否存在值为data的节点,存在返回该节点的地址,否则返回nullptr
Node* Find(const T& data)
{
Node* cur = _pRoot;
while (cur)
{
if (data == cur->_data)
{
return cur;
}
else if (data < cur->_data)
{
cur = cur->_pLeft;
}
else
{
cur = cur->_pRight;
}
}
return nullptr;
}
// 获取红黑树最左侧节点
Node* LeftMost()
{
Node* cur = _pRoot;
while (cur->_pLeft)
{
cur = cur->_pLeft;
}
return cur;
}
// 获取红黑树最右侧节点
Node* RightMost()
{
Node* cur = _pRoot;
while (cur->_pRight)
{
cur = cur->_pRight;
}
return cur;
}
// 检测红黑树是否为有效的红黑树,注意:其内部主要依靠_IsValidRBTRee函数检测
bool IsValidRBTRee()
{//黑色个数算上_pRoot
if (!_pRoot) return true;
int pathBlack = 0;
Node* cur = _pRoot;
while (cur)
{
if (cur->_colour == BLACK)
{
pathBlack++;
}
cur = cur->_pLeft;
}
return _IsValidRBTRee(_pRoot, 0, pathBlack);
}
private:
bool _IsValidRBTRee(Node* root, size_t blackCount, size_t pathBlack)
{
if (!root)
{
return blackCount == pathBlack;
}
int add = root->_colour == BLACK ? 1 : 0;
return _IsValidRBTRee(root->_pLeft, blackCount+add, pathBlack) && _IsValidRBTRee(root->_pRight, blackCount + add, pathBlack);
}
// 左单旋
void RotateL(Node* grand)
{
Node* subR = grand->_pRight;
Node* subRL = subR->_pLeft;
if (grand == _pRoot)
{
_pRoot = subR;
subR->_pParent = nullptr;
}
else
{
subR->_pParent = grand->_pParent;
if (grand == grand->_pParent->_pLeft)
{
grand->_pParent->_pLeft = subR;
}
else
{
grand->_pParent->_pRight = subR;
}
}
grand->_pRight = subRL; if (subRL) subRL->_pParent = grand;
grand->_pParent = subR, subR->_pLeft = grand;
}
// 右单旋
void RotateR(Node* grand)//旋转不变颜色, 函数外变颜色
{
Node* subL = grand->_pLeft;
Node* subLR = subL->_pRight;
if (grand == _pRoot)
{
_pRoot = subL;
subL->_pParent = nullptr;
}
else
{
subL->_pParent = grand->_pParent;
if (grand == grand->_pParent->_pLeft)
{
grand->_pParent->_pLeft = subL;
}
else
{
grand->_pParent->_pRight = subL;
}
}
grand->_pLeft = subLR; if(subLR) subLR->_pParent = grand;
grand->_pParent = subL, subL->_pRight = grand;
}
void RotateLR(Node* grand)
{
RotateL(grand->_pLeft);
RotateR(grand);
}
void RotateRL(Node* grand)
{
RotateR(grand->_pRight);
RotateL(grand);
}
private:
Node* _pRoot;
void _Inorder(Node* root)
{
if (!root) return;
_Inorder(root->_pLeft);
cout << root->_data << " ";
_Inorder(root->_pRight);
}
};
void testRBTree()
{
RBTree<int> rb;
rb.Insert(2);
rb.Insert(6);
rb.Insert(4);
rb.Insert(9);
rb.Insert(11);
rb.Insert(78);
rb.Insert(36);
rb.Insert(27);
rb.Inorder();
cout << endl;
int array[10] = { 1, 2, 6, 4, 9, 10, 11, 27, 55, 78 };
for (const auto& e : array)
{
auto find = rb.Find(e);
if (!find)cout << e << " 不在树中" << endl;
else
{
if (find->_data == e)
{
cout << e << " 在树中, 返回值正确" << endl;
}
else
{
cout << e << " 在树中, 但是返回值错误" << endl;
}
}
}
cout << rb.IsValidRBTRee() << endl;
cout << "hello world" << endl;
}
int main()
{
testRBTree();
return 0;
}