#pragma once
#include "my_sorting.h"
#include <vector>
class RBTree
{
private:
struct TreeNode
{
int val;
char color;
TreeNode* left;
TreeNode* right;
TreeNode* fa;
TreeNode(int v): val(v), left(0), right(0), fa(0), color('b'){}
~TreeNode(){cout<<"node val at "<<val<<" has been deleted!\n";}
};
TreeNode *root;
int nodenum;
public:
RBTree(void): root(0){}
// 快速设置左右孩子
void setright(TreeNode* nd, TreeNode* nd1){
if (nd) nd->right = nd1;
if (nd1) nd1->fa = nd;
}
void setleft(TreeNode* nd, TreeNode* nd1){
if (nd) nd->left = nd1;
if (nd1) nd1->fa = nd;
}
// 中序遍历
void printinoder(TreeNode *nd)
{
if(nd){
printinoder(nd->left);
cout<<nd->val<<" ";
printinoder(nd->right);
}
}
// 找到值为v的节点,返回其指针
TreeNode* find(int v){
TreeNode *nd = root;
while(nd && nd->val!=v){
if (v < nd->val)
nd = nd->left;
else
nd = nd->right;
}
return nd;
}
// 左旋操作
void left_rotate(TreeNode* x){
TreeNode* y = x->right;
if(!y) // 左旋操作中x的右节点必须非空
return;
setright(x, y->left);
y->fa = x->fa;
if (x==root)
root = y;
else{
if(x==x->fa->left)
setleft(x->fa, y);
else
setright(x->fa, y);
}
setleft(y, x);
}
// 右旋操作
void right_rotate(TreeNode* x){
TreeNode* y = x->left;
if(!y) // 左旋操作中x的右节点必须非空
return;
setleft(x, y->right);
y->fa = x->fa;
if (x==root)
root = y;
else{
if(x==x->fa->right)
setright(x->fa, y);
else
setleft(x->fa, y);
}
setright(y, x);
}
// 红黑树插入节点
void RB_insert(int v){
nodenum ++;
if(!root){
root = new TreeNode(v);
return;
}
TreeNode* pre, *nd = root;
bool isright;
while(nd){
pre = nd;
if (v < nd->val){
nd = nd->left;
isright = false;
}else{
nd = nd->right;
isright = true;
}
}
TreeNode *z = new TreeNode(v);;
if(isright)
setright(pre,z);
else
setleft(pre,z);
z->color = 'r';
RB_insert_fix_up(z);
}
// 删除操作!比较复杂,先不写了
// 插入后调整,保持红黑属性
void RB_insert_fix_up(TreeNode* z){
while(z->fa && z->fa->color=='r'){ // 在z的父为红的情况下进行循环
if(!z->fa->fa)
break; // 如果z没有祖父节点,则退出
if(z->fa==z->fa->fa->left){
TreeNode* y = z->fa->fa->right; // y为z的叔节点
if(y && y->color=='r'){ // 1、父、叔皆红,则将祖父置红,父、叔置黑
z->fa->color ='b';
y->color = 'b';
z->fa->fa->color = 'r';
z = z->fa->fa; // z向上回溯置祖父节点
}else{
if (z==z->fa->right){ // 2、父红叔黑,且z为其父的右孩子(2完成后一定会到3)
z = z->fa;
left_rotate(z);
}
z->fa->color = 'b'; // 3、父红叔黑,且z为其父的左孩子
z->fa->fa->color = 'r';
right_rotate(z->fa->fa);
}
}else{ // 对称情况
TreeNode* y = z->fa->fa->left;
if(y && y->color=='r'){
z->fa->color ='b';
y->color = 'b';
z->fa->fa->color = 'r';
z = z->fa->fa;
}else{
if (z==z->fa->left){
z = z->fa;
right_rotate(z);
}
z->fa->color = 'b';
z->fa->fa->color = 'r';
left_rotate(z->fa->fa);
}
}
root->color = 'b';
}
}
TreeNode* getroot(){return root;}
// 按层打印树
void printlevel(){
vector<vector<int> > res;
vector<TreeNode*> q(1,root);
TreeNode* nd;
int level=0;
while(!q.empty()){
int sz=q.size();
res.push_back(vector<int>());
for(int i=0;i<sz;i++){
nd = q.front();
res[level].push_back(nd->val);
q.erase(q.begin());
if(nd->left) q.push_back(nd->left);
if(nd->right) q.push_back(nd->right);
}
level++;
}
for (int i=0;i<level;i++){
for(size_t j=0;j<res[i].size();j++)
cout<<res[i][j]<<' ';
cout<<endl;
}
}
};
性能测试:
RBTree rbt;
for (int i=0;i<n;i++)
rbt.RB_insert(i);
rbt.printinoder(rbt.getroot()); // n=10^5 时耗时 0.172 秒(性能非常好!)
rbt.printlevel();
n=15时结果如下:
其中黑色节点用圆圈标识,从图中可见,树的黑高为3,树的最长路径为6,最短为3,符合红黑性质(最长/最短<=3)最长路径不会比最短路径长出2倍
补充红黑树的几条性质如下(图片来自算法导论):