红黑树的性质:
1.每个结点的链接要么是红的要么是黑的;
2.根结点的链接是黑的;
3.每个叶结点的左右nullptr指针都是黑的;
4.如果一个父节点链接是红的,那么它的两个儿子的链接都是黑的;
5.对于任意结点而言,其到叶结点树尾端到根节点的每条路径都包含相同数目的黑链接。
#include<iostream>
#define RED true
#define BLACK false
template<class T>
class TreeNode
{
public:
T m_nkey;
int m_nValue;
int N;
bool color;
TreeNode* pLeft, * pRight;
TreeNode(T _key, int _value, int _N, bool _color)
:m_nkey(_key), m_nValue(_value), N(_N),color(_color), pLeft(nullptr), pRight(nullptr) {}
};
template<class Key>
class RedBlackTree
{
TreeNode<Key>* pRoot;
public:
RedBlackTree() :pRoot(nullptr) {};
~RedBlackTree() { clear(); }
int size();//树节点数量
void put(Key _key, int _value);//插入新节点
void printfTree() { _printfTree(pRoot); }//打印树
void deleteMin();//删除最小键
void deleteMax();//删除最大键
void deleteNode(Key key);//删除节点
void clear() { _clear(pRoot); }//手动销毁树
private:
//******************************************************************************
//辅助方法
//******************************************************************************
void _printfTree(TreeNode<Key>* root){
if (root)
{
std::cout << "(" << root->m_nkey << "," << root->color << ")" << " ";
_printfTree(root->pLeft);
_printfTree(root->pRight);
}
}
void _clear(TreeNode<Key>*& root);
TreeNode<Key>* _put(TreeNode<Key>* root, Key _key, int _value);
TreeNode<Key>* _deleteMin(TreeNode<Key>* root);
TreeNode<Key>* _deleteMax(TreeNode<Key>* root);
TreeNode<Key>* _deleteNode(TreeNode<Key>* root, Key _key);
TreeNode<Key>* moveNodeLeft(TreeNode<Key>* node);
TreeNode<Key>* moveNodeRight(TreeNode<Key>* node);
TreeNode<Key>* _getMin(TreeNode<Key>* root);
int _getValue(TreeNode<Key>* node,Key key);
int _size(TreeNode<Key>* node);
bool isRed(TreeNode<Key>* node);
void flipColor(TreeNode<Key>* node);
TreeNode<Key>* rotateLeft(TreeNode<Key>* node);
TreeNode<Key>* rotateRight(TreeNode<Key>* node);
TreeNode<Key>* blance(TreeNode<Key>* node);
};
//******************************************************************************
//方法实现
//******************************************************************************
template<class Key>
void RedBlackTree<Key>::_clear(TreeNode<Key>*& root)
{//此处递归删除时要引用,否则内存不会为NULL
if (root)
{
_clear(root->pLeft);
_clear(root->pRight);
delete root;
root = nullptr;
}
}
template<class Key>
void RedBlackTree<Key>::put(Key _key, int _value)
{
pRoot = _put(pRoot, _key, _value);
pRoot->color = BLACK;//红黑树性质:根节点为黑色
}
template<class Key>
TreeNode<Key>* RedBlackTree<Key>::_put(TreeNode<Key>* root, Key _key, int _value)
{
if (root == nullptr)
return root = new TreeNode<Key>(_key, _value, 1, RED);//如果没有这个节点则new块内存出来
if (_key < root->m_nkey)root->pLeft = _put(root->pLeft, _key, _value);//左递归
else if (_key > root->m_nkey)root->pRight = _put(root->pRight, _key, _value);//右递归
else root->m_nValue = _value;
if (isRed(root->pRight) && !isRed(root->pLeft))root = rotateLeft(root);//第一层变换,当右节点链接为红色时左旋
if (isRed(root->pLeft) && isRed(root->pLeft->pLeft))root = rotateRight(root);//第二层变换,不允许出现4-节点,即没有两根连续的红色链接
if (isRed(root->pLeft) && isRed(root->pRight))flipColor(root);//第三层变换,当节点的左右子节点链接都为红色时,将链接颜色转换
root->N = _size(root->pLeft) + _size(root->pRight) + 1;//更新节点数量
return root;
}
template<class Key>
void RedBlackTree<Key>::deleteNode(Key key)
{
if (pRoot)
{//一定要在树不为空的情况下进行
if (!isRed(pRoot->pLeft) && !isRed(pRoot->pRight))//这个点可加,可不加,算是一种约定俗成
pRoot->color = RED;
pRoot = _deleteNode(pRoot, key);
if (pRoot)pRoot->color = BLACK;//根节点默认黑色
}
else
{
std::cout << "树为空!" << std::endl;
return;
}
}
template<class Key>
TreeNode<Key>* RedBlackTree<Key>::_deleteNode(TreeNode<Key>* root, Key _key)
{ //结合删除最小节点和删除最大节点
if (root)
{
if (_key < root->m_nkey)
{//往左左子树走
if (root->pLeft && !isRed(root->pLeft) && !isRed(root->pLeft->pLeft))
root = moveNodeLeft(root);
root->pLeft = _deleteNode(root->pLeft, _key);
}
else
{//往右子树走
if (isRed(root->pLeft))
root = rotateRight(root);
if (_key == root->m_nkey && root->pRight == nullptr)
{//当节点为最右节点时,可直接删除
delete root;
return nullptr;
}
//判断该点是否是2-节点
if (root->pRight && !isRed(root->pRight) && !isRed(root->pRight->pLeft))
root = moveNodeRight(root);
if (_key == root->m_nkey)
{//在树中找到节点,则用右子树的最小节点代替,然后删除掉左子树的最小节点
root->m_nValue = _getValue(root->pRight, _getMin(root->pRight)->m_nkey);
root->m_nkey = _getMin(root->pRight)->m_nkey;
root->pRight = _deleteMin(root->pRight);
}
else root->pRight = _deleteNode(root->pRight, _key);
}
}
else
{
std::cout << "节点不存在!!!" << std::endl;
}
return blance(root);
}
template<class Key>
void RedBlackTree<Key>::deleteMin()
{
if (pRoot)
{//同删除
if (!isRed(pRoot->pLeft) && !isRed(pRoot->pRight))
pRoot->color = RED;
pRoot = _deleteMin(pRoot);
if (pRoot)pRoot->color = BLACK;
}
else
{
std::cout << "树为空!" << std::endl;
return;
}
}
template<class Key>
TreeNode<Key>* RedBlackTree<Key>::_deleteMin(TreeNode<Key>* root)
{
if (root->pLeft == nullptr)
{
delete root;
return nullptr;
}
//判断是否为2-节点
if (!isRed(root->pLeft) && !isRed(root->pLeft->pLeft))
root = moveNodeLeft(root);//如果是2-节点,就变成一个3-节点
root->pLeft = _deleteMin(root->pLeft);
return blance(root);
}
template<class Key>
void RedBlackTree<Key>::deleteMax()
{
if (pRoot)
{//同删除
if (!isRed(pRoot->pLeft) && !isRed(pRoot->pRight))
pRoot->color = RED;
pRoot = _deleteMax(pRoot);
if (pRoot)pRoot->color = BLACK;
}
else
{
std::cout << "树为空!" << std::endl;
return;
}
}
template<class Key>
TreeNode<Key>* RedBlackTree<Key>::_deleteMax(TreeNode<Key>* root)
{
if (isRed(root->pLeft))//删除最大节点,如果该节点为3-节点 进行右旋,为后面的父节点往下走形成3-节点形成条件
root = rotateRight(root);
if (root->pRight == nullptr)
{
delete root;
return nullptr;
}
//判断是否为2-节点
if (!isRed(root->pRight) && !isRed(root->pRight->pLeft))
root = moveNodeRight(root);
root->pRight = _deleteMax(root->pRight);
return blance(root);
}
template<class Key>
int RedBlackTree<Key>::size()
{
return _size(pRoot);
}
template<class Key>
int RedBlackTree<Key>::_size(TreeNode<Key>* node)
{
if (node == nullptr)return NULL;
return node->N;
}
template<class Key>
bool RedBlackTree<Key>::isRed(TreeNode<Key>* node)
{//判断是否为红链接
if (node == nullptr)return false;
return node->color==RED;
}
template<class Key>
void RedBlackTree<Key>::flipColor(TreeNode<Key>* node)
{/*方法作用:
1、当左右链接为红时,进行变化
2、向父节点借节点
3、还给父节点节点
*/
node->color = !node->color;
node->pLeft->color = !node->pLeft->color;
if(node->pRight)
node->pRight->color = !node->pRight->color;
}
template<class Key>
TreeNode<Key>* RedBlackTree<Key>::rotateLeft(TreeNode<Key>* node)
{//左旋
TreeNode<Key>* x = node->pRight;
node->pRight = x->pLeft;
x->pLeft = node;
x->color = x->pLeft->color;
x->pLeft->color = RED;
x->N = node->N;
node->N = _size(node->pLeft) + _size(node->pRight) + 1;
return x;
}
template<class Key>
TreeNode<Key>* RedBlackTree<Key>::rotateRight(TreeNode<Key>* node)
{//右旋
TreeNode<Key>* x = node->pLeft;
node->pLeft = x->pRight;
x->pRight = node;
x->color = x->pRight->color;
x->pRight->color = RED;
x->N = node->N;
node->N = _size(node->pLeft) + _size(node->pRight) + 1;
return x;
}
template<class Key>
TreeNode<Key>* RedBlackTree<Key>::blance(TreeNode<Key>* node)
{//平衡
if (node)
{
if (node->pRight)node = rotateLeft(node);
if (isRed(node->pLeft) && isRed(node->pLeft->pLeft))node = rotateRight(node);
if (isRed(node->pLeft) && isRed(node->pRight))flipColor(node);
node->N = _size(node->pLeft) + _size(node->pRight) + 1;
}
return node;
}
template<class Key>
TreeNode<Key>* RedBlackTree<Key>::moveNodeLeft(TreeNode<Key>* node)
{
flipColor(node);//向父节点借一个节点,变成3-节点
if (node->pRight && isRed(node->pRight->pLeft))
{//如果兄弟节点存在且不为2-节点,则从兄弟节点借节点过来
node->pRight = rotateRight(node->pRight);
node = rotateLeft(node);
flipColor(node);
}
return node;
}
template<class Key>
TreeNode<Key>* RedBlackTree<Key>::moveNodeRight(TreeNode<Key>* node)
{//同上
flipColor(node);
if (node->pLeft && isRed(node->pLeft->pLeft))
{
node = rotateRight(node);
flipColor(node);
}
return node;
}
template<class Key>
int RedBlackTree<Key>::_getValue(TreeNode<Key>* node, Key _key)
{
if (_key < node->m_nkey) return _getValue(node->pLeft,_key);
else if (_key > node->m_nkey)return _getValue(node->pRight,_key);
else return node->m_nValue;
}
template<class Key>
TreeNode<Key>* RedBlackTree<Key>::_getMin(TreeNode<Key>* node)
{
if (node->pLeft == nullptr)return node;
else return _getMin(node->pLeft);
}
int main(int argc, char* argv[])
{
RedBlackTree<char> B;
B.put('A', 10);
B.put('B', 10);
B.put('C', 10);
B.put('D', 10);
B.printfTree();
std::cout << "\n";
B.deleteNode('D');
B.printfTree();
//std::cout << "\n";
//B.deleteNode('A');
//B.printfTree();
std::cin.get();
return 0;
}
(●新手一枚,有错误之处请大佬多多指正●)