算法与数据结构之左偏红黑树
1.预备知识
1.1 2-3树
2-3树是由2-节点与3-节点共同组成的树,3-节点有两个键,有三个分支
但由于2-3树的实现的插入情况很多,一一实现困难,所以我们有了另外一种替代方法,即红黑树
每个节点的红色即代表该节点与其父节点构造一个3-节点,将红键拉平即是2-3树的模样
2. Node结构体
const bool RED = true;
const bool BLACK = false;//方便起见,定义常量
template<typename T1,typename T2>
class Node
{
public:
T1 Key;
T2 Val;
Node<T1, T2>Left, Right;
bool Color;//TRUE为红色,FALSE为黑色
int N;
Node(T1 key, T2 val,bool color)
{
Key = key;
Val = val;
Left = nullptr;
Right = nullptr;
N = 1;
Color = color;
}
};
3.旋转与确认是否为红
template<typename T1, typename T2>
Node<T1, T2>* RedBlackTree<T1, T2>::RotateLeft(Node<T1, T2>* x)
{
Node<T1,T2>*h = x->Right;
x->Right = h->Left;
h->Left = x;
h->Color = x->Color;
x->Color = RED;
h->N = x->N;
x->N = size(x->Left) + size(x->Right) + 1;
return h;
}
template<typename T1, typename T2>
Node<T1, T2>* RedBlackTree<T1, T2>::RotateRight(Node<T1, T2>* x)
{
Node<T1, T2>*h = x->Left;
x->Left = h->Right;
h->Left = x;
h->Color = x->Color;
x->Color = RED;
h->N = x->N;
x->N = size(x->Left) + size(x->Right) + 1;
return h;
}
template<typename T1, typename T2>
bool RedBlackTree<T1, T2>::IsRed(Node<T1, T2>* x)
{
if (x == nullptr)
return false;
return x->Color == RED;
}
4.插入方法
4.1代码实现
template<typename T1, typename T2>
void RedBlackTree<T1, T2>::FlipColor(Node<T1, T2>* x)
{
x->Left->Color = !x->Left->Color;
x->Right->Color = !x->Right->Color;
x->Color = !x->Color;
}
template<typename T1, typename T2>
Node<T1, T2>* RedBlackTree<T1, T2>::put(Node<T1, T2>* x, T1 key, T2 val)
{
if (x == nullptr)
{
Node<T1, T2>*temp = new Node(key, val, RED);
return temp;
}
if (x->Key > key)
x->Left = put(x->Left, key, val);
else if (x->Key < key)
x->Right = put(x->Right, key, val);
else
x->Val = val;
if (!IsRed(x->Left) && IsRed(x->Right))
x = RotateLeft(x);
if (x->Left != nullptr&&IsRed(x->Left) && IsRed(x->Left->Left))
x = RotateRight(x);
if (IsRed(x->Left) && IsRed(x->Right))
FlipColor(x);
x = size(x->Left) + size(x->Right) + 1;
return x;
}
4.2代码解释
if (!IsRed(x->Left) && IsRed(x->Right))
x = RotateLeft(x); //将红色的右节点翻转至父节点位置,而父节点变成红色的左节点
if (x->Left != nullptr&&IsRed(x->Left) && IsRed(x->Left->Left))
x = RotateRight(x); //将连续的两个红色节点中的第一个红色节点翻转至右
if (IsRed(x->Left) && IsRed(x->Right))
FlipColor(x); //若两子节点均为红色,那么两个节点红色取消,将父节点变为红色
5.删除
5.1 平衡方法
template<typename T1, typename T2>
Node<T1, T2>* RedBlackTree<T1, T2>::Balance(Node<T1, T2>* x)
{
if (IsRed(x->Right))
x = RotateLeft(x);
if (x->Left != nullptr&&IsRed(x->Left) && IsRed(x->Left->Left))
x = RotateRight(x);
if (IsRed(x->Left) && IsRed(x->Right))
FlipColor(x);
x->N = size(x->Left) + size(x->N) + 1;
return x;
}
5.2删除最小值
公有调用:
void DeleteMin()
{
if (Root == nullptr)
return;
if (!IsRed(Root->Left)&&!IsRed(Root->Right))
Root->Color = RED;
Root = DeleteMin(ROOT);
if (Root != nullptr)
Root->Color = BLACK;
}
私有实现:
template<typename T1, typename T2>
Node<T1, T2>* RedBlackTree<T1, T2>::RemoveRedLeft(Node<T1, T2>* x)
{
FlipColor(x);
if (x->Right&&IsRed(x->Right->Left))
{
x->Right = RotateRight(x->Right);
x = RotateLeft(x->Left);
FlipColor(x);
}
return x;
}
template<typename T1, typename T2>
Node<T1, T2>* RedBlackTree<T1, T2>::DeleteMin(Node<T1, T2>* x)
{
if (x->Left == nullptr)
{
delete x;
return nullptr;
}
if (!IsRed(x->Left) && !IsRed(x->Left->Left)
x = RemoveRedLeft(x);
x->Left = DeleteMin(x->Left);
return Balance(x);
}
5.3 删除最大值
公有调用
void DeleteMax()
{
if (Root == nullptr)
return;
if (!IsRed(Root->Left) && !IsRed(Root->Right))
Root->Color = RED;
Root = DeleteMax(Root);
if (Root != nullptr)
Root->Color = BLACK;
}
私有实现
template<typename T1, typename T2>
Node<T1, T2>* RedBlackTree<T1, T2>::RemoveRedRight(Node<T1, T2>* x)
{
FlipColor(x);
if (IsRed(x->Left->Left))
{
x = RotateRight(x);
FlipColor(x);
}
return x;
}
template<typename T1, typename T2>
Node<T1, T2>* RedBlackTree<T1, T2>::DeleteMax(Node<T1, T2>* x)
{
if (x->Right == nullptr)
{
delete x;
return nullptr;
}
if (!IsRed(x->Right) && !IsRed(x->Right->Left))
x = RemoveRedRight(x);
x->Right = DeleteMax(x->Right);
return Balance(x);
}
5.4删除方法
template<typename T>
Node<T>* RBT<T>::DeleteKey(Node<T>* h, T key)
{
if (h->Key > key)
{
if (!IsRed(h->left) && !IsRed(h->left->left))
h = MoveRedLeft(h);
h->left = DeleteKey(h->left, key);
}
else
{
if(IsRed(h->left))
h = RotateRight(h);
if (h->Key == key&&h->Right == nullptr)
{
delete h;
cout << "delete" << endl;
return nullptr;
}
if (!IsRed(h->Right) && !IsRed(h->Right->left))
h = MoveRedRight(h);
if (h->Key == key)
{
Node<T>*temp = GetMin(h->Right);
h->Key = temp->Key;
h->Right = DeleteMin(h->Right);
}
else
h->Right = DeleteKey(h->Right, key);
}
return Balance(h);
}