红黑树规则
每个节点不是黑色就是虹色
根节点为黑色
每条路径的黑节点之和相等
每个红节点一定和黑节点相连,黑节点可以和任意节点相连
最长路径小于等于最短路径的二倍
插入一个节点后,怎么保持原有规则
更新祖宗节点的颜色
grandpa
parent uncle
cur
cur为被插入节点,
如果parent存在,且parent的颜色为黑,停止更新
根据uncle的存在或是颜色来判断是否更新颜色 还是 进行旋转以保持原有规则
如果parent节点的颜色为红色,且uncle节点存在颜色为红色,把parent和uncle节点颜色更新成黑色,将grandpa颜色更新成红色,令cur=grandpa,接着循环判断
旋转
如果parent节点的颜色为红色,uncle节点不存在或颜色为黑色,要进行旋转,旋转方式和AVLTree中情况相同
単旋和双旋
単旋就是节点一边高
双旋就是节点不单是一边高
右旋
左边节点高,进行右旋
grandpa
parent
cur
parent是grandpa的左孩子,cur是parent的左孩子,这种情况要右旋
grandpa
parent
cur
parent是grandpa的右孩子,cur是parent的左孩子,先右旋,在左旋
先将 parent 以parent为旋转点 ,进行右·旋
cur
得到 grandpa 以cur为旋转点,进行左旋
cur
parent
红黑树迭代器
新实现一个类(_iterator),在红黑树中实现begin()等函数,把_iterator在红黑树中重命名
++重载:由于红黑树是用中序遍历也就是 先遍历左子树,在遍历根,最后遍历右子树,
也就是说红黑中的一个节点++后,
如果有右子树,就会跑到右子树最左节点
如果没有右子树,就要判断,根节点是父节点的左孩子还是右孩子,
如果是左孩子,就跑到父节点
如果是右孩子,则向上遍历,直到找到,或父节点为空(也就是到头)
把红黑树封装成set和map(要求只用一份红黑树代码)
Insert的返回类型为pair<iterator,bool>,返回iterator(迭代器)可以避免迭代器失效的情况,bool表示插入是否成功(返回1代表原数据没有,返回0代表存在)
在map和set类中,只需要调用红黑树中的函数即可
封装map和set就像是基类和子类的关系
子类在父类的基础上添加一些东西
代码部分
RedBlackTree.h
#pragma once
#include<iostream>
using namespace std;
enum Color
{
RED,
BLACK
};
template<class K, class V >
class RBNode
{
public:
typedef RBNode<K, V>Node;
Node* _left;
Node* _right;
Node* _parent;
Color _color;
pair<K, V>_kv;
public:
RBNode(pair<K, V>kv)
:_left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _kv(kv)
, _color(RED)
{}
};
template<class K, class V>
class RBTree
{
public:
typedef RBNode<K, V> Node;
private:
Node* _root = nullptr;
public:
//构造函数
RBTree()
:_root(nullptr)
{}
//析构函数
void _Destory(Node* root)
{
if (root == nullptr)
return;
_Destory(root->_left);
_Destory(root->_right);
delete root;
}
~RBTree()
{
_Destory(_root);
}
//拷贝构造函数
Node* _Copy(Node* root)
{
if (root == nullptr)
return nullptr;
Node* left = _Copy(root->_left);
Node* right = _Copy(root->_right);
Node* newnode = new Node;
newnode->_left = left;
newnode->_right = right;
newnode->_color = root->_color;
newnode->_kv = root->_kv;
return newnode;
}
RBTree(const Node& t)
{
_Copy(&t);
}
//赋值
RBTree<K, V>operator=(RBTree<K, V>t)
{
swap(_root, t._root);
return *this;
}
//左旋
void RotateL(Node* cur)
{
Node* parent = cur->_parent;
Node* curL = cur->_left;
Node* gradpa = parent->_parent;
if (gradpa && gradpa->_left == parent)
gradpa->_left = cur;
if(gradpa && gradpa->_right == parent)
gradpa->_right = cur;
if (gradpa == nullptr)
_root = cur;
parent->_right = cur->_left;
parent->_parent=cur;
cur->_parent = gradpa;
cur->_left = parent;
}
//右旋
void RotateR(Node* cur)
{
Node* parent = cur->_parent;
Node* curR = cur->_right;
Node* gradpa = parent->_parent;
if (gradpa && gradpa->_left == parent)
gradpa->_left = cur;
if (gradpa && gradpa->_right == parent)
gradpa->_right = cur;
parent->_left = curR;
parent->_parent = cur;
cur->_right = parent;
cur->_parent = gradpa;
}
//插入
bool Insert(pair<K, V>kv)
{
if (_root == nullptr)
{
_root = new Node(kv);
_root->_color = BLACK;
return true;
}
Node* cur = _root;
//找到要插入的位置
Node* parent = nullptr;
while (cur)
{
if (cur->_kv.first < kv.first)
{
parent = cur;
cur = cur->_right;
}
else if (cur->_kv.first > kv.first)
{
parent = cur;
cur = cur->_left;
}
else
{
return false;
}
}
cur= new Node(kv);
Node* gradpa =nullptr;
Node* uncle = nullptr;
cur->_parent = parent;
//判断单旋还是双旋
if (parent->_kv.first > kv.first)
{
//新插入节点位置左边还是右边
//新节点插入左边
parent->_left = cur;
//parent可能是根节点
if (parent->_color == BLACK)
return 1;
//parent一定是红色,且一定有父节点
gradpa = parent->_parent;
//判断uncle和parent谁是左节点谁是右节点
if (parent == gradpa->_left)
uncle = gradpa->_right;
else
uncle = gradpa->_left;
}
else
{
//新节点插在右边
parent->_right = cur;
if (parent->_color == BLACK)
return 1;
gradpa = parent->_parent;
if (parent == gradpa->_left)
uncle = gradpa->_right;
else
uncle = gradpa->_left;
}
while (cur)
{
if (parent->_color == BLACK)
{
break;
}
else
{
//更新节点颜色
if (uncle && uncle->_color == RED)
{
uncle->_color = parent->_color = BLACK;
gradpa->_color = RED;
cur = gradpa;
parent = cur->_parent;
if (parent == nullptr || parent->_color == BLACK)
break;
gradpa = parent->_parent;
if (parent->_right == cur)
uncle = gradpa->_left;
else
uncle = gradpa->_right;
}
//旋转
else
{
if (cur == parent->_left)
{
if (parent == gradpa->_left)
{
RotateR(parent);
gradpa->_color = RED;
parent->_color = BLACK;
break;
}
else
{
RotateR(cur);
RotateL(cur);
cur->_color = BLACK;
gradpa->_color = RED;
break;
}
}
else
{
if (parent == gradpa->_right)
{
RotateL(parent);
gradpa->_color = RED;
parent->_color = BLACK;
break;
}
else
{
RotateL(cur);
RotateR(cur);
cur->_color = BLACK;
gradpa->_color = RED;
break;
}
}
}
}
}
_root->_color = BLACK;
}
//中序遍历
void _Inorder(Node* root)
{
if (root == nullptr)
return;
_Inorder(root->_left);
cout << root->_kv.first<<" "<<root->_color<<" ";
_Inorder(root->_right);
}
void Inorder()
{
_Inorder(_root);
}
};
test.cpp
#include"RedBlackTree.h"
int main()
{
RBTree<int, int> t;
t.Insert(make_pair(1,1));
t.Insert(make_pair(8,1));
t.Insert(make_pair(7,1));
t.Insert(make_pair(10,1));
t.Insert(make_pair(-11,1));
t.Insert(make_pair(-19,1));
t.Insert(make_pair(-1119,1));
t.Insert(make_pair(-20,1));
t.Insert(make_pair(-109,1));
t.Insert(make_pair(-189,1));
//t.Insert(make_pair(5,1));
t.Inorder();
return 0;
}