浅析红黑树原理以及实现
bool Insert(const K& key, const V& val)
{
//_Insert(_root, x, y);
if (_root == NULL)
{
_root = new Node(key, val);
_root->_col = BLACK;
}
Node* cur = _root;
Node* parent = cur;
while (cur)
{
if (cur->_key > key)
{
parent = cur;
cur = cur->_left;
}
else if (cur->_key < key)
{
parent = cur;
cur = cur->_right;
}
else if (cur->_key == key)
{
return true;
}
}
if (parent->_key > key)
{
parent->_left = new Node(key, val);
parent->_left->_parent = parent;
cur = parent->_left;
}
else
{
parent->_right = new Node(key, val);
parent->_right->_parent = parent;
cur = parent->_right;
}
//目前父亲节点,插入节点,叔叔节点已经就绪.
while(parent && parent->_col == RED)
{
Node* parentparent = parent->_parent;
Node* uncle = NULL;
if (parentparent->_left == parent)
uncle = parentparent->_right;
else
uncle = parentparent->_left;
if(uncle && uncle->_col == RED)
{
parentparent->_col = RED;
parent->_col = BLACK;
uncle->_col = BLACK;
cur = parentparent;
parent = cur->_parent;
}
else if (uncle == NULL || uncle->_col == BLACK)
{
if (parentparent->_left == parent)
{
if (parent->_left == cur)
{
RotateR(parentparent);
parent->_col = BLACK;
}
else
{
RotateLR(parentparent);
cur->_col = BLACK;
}
}
else
{
if (parent->_right == cur)
{
RotateL(parentparent);
parent->_col = BLACK;
}
else
{
RotateRL(parentparent);
cur->_col = BLACK;
}
}
parentparent->_col = RED;
if (parentparent == _root)
{
_root = parent;
}
}
else
{
assert(false);
}
if (_root->_col == RED)
{
_root->_col = BLACK;
}
}
return false;
}
我们要删除del这个时候,直接删除del成本太高了,然后我们寻找一个边缘节点跟他交换,然后再删除它.所以呢,这样删除的成本是
最小的. 删除分三个情况:
1.del的左为空.
2.del的右为空.
3.del的左右都不为空.
前两种很容易思考,第三种左右都不为空的情况才需要我们的边缘替换法.所以我这里附上搜索二叉树的删除的代码. 红黑树删除的代
码暂时我还没有解决所以这里之后搜索二叉树的删除代码. 我们可以想着思考思考说不定就写完了.
代码实现:
bool Remove(const K& key)
{
if (_root == NULL)
{
return false;
}
Node* cur = _root;
Node* parent = NULL;
while (cur)
{
if (cur->key > key)
{
parent = cur;
cur = cur->_left;
}
else if (cur->key < key)
{
parent = cur;
cur = cur->_right;
}
else if (cur->key == key)
{
break;
}
}
Node* del = cur;
if (cur->_left == NULL) //左为空
{
if (parent == NULL)
{
_root = cur->_right;
if (_root)
_root->_parent = NULL;
}
else
{
if (parent->_left == cur)
parent->_left = cur->_right;
else
parent->_right = cur->_right;
if (cur->_right)
cur->_right->_parent = parent;
}
}
else if (cur->_right == NULL)//右为空
{
if (parent == NULL)
{
_root = cur->_left;
if (_root)
_root->_parent = NULL;
}
else
{
if (parent->_left == cur)
parent->_left = cur->_left;
else
parent->_right = cur->_left;
if (cur->_left)
cur->_left->_parent = parent;
}
}
else //左右都不为空
{
if (parent == NULL || cur == parent->_left) //如果cur在左边.
{
del = cur->_right;
while (del->_left)
{
del = del->_left;
}
del->_parent->_left = del->_right;;
}
else //cur在parent的右边.
{
del = cur->_left;
while (del->_right)
{
del = del->_right;
}
del->_parent->_right = del->_left;
}
cur->key = del->key;
cur->val = del->val;
}
delete del;
}
编写一个检验该二叉树是否为红黑树的程序:
这里首先解决一个最棘手的问题,如何判断一个路径上面的黑节点相同? 我们很容易想到,可以先遍历一条路径找到一个基准值,然
后和其他路径做比较,代码实现就是每次走到叶子结点的时候,比较该条路径的黑色节点节点个数是否和基准值相等? 如果不相等
那么返回false. 所以我们参数里面需要一个m(传递黑色节点基准值)和n(记录该条路径上面的黑色节点个数).
那么我们来瞧瞧代码实现:
bool ISRBtree()
{
if (_root->_col == RED)
{
return false;
}
size_t n = 0;
size_t m = 0;
Node* cur = _root;
while (cur)
{
if (cur->_col == BLACK)
{
n++;
}
cur = cur->_left;
}
return _ISRBtree(_root, m, n);
}
bool _ISRBtree(Node* root, size_t m, size_t n)
{
if (root == NULL)
{
if (m == n)
return true;
else
return false;
}
if (root->_col == BLACK)
{
m++;
}
if (root->_col == RED && root->_parent && root->_parent->_col == RED)
{
return false;
}
return _ISRBtree(root->_left, m, n) && _ISRBtree(root->_right, m, n);
}
演示结果:
总结
红黑树是一个非常重要的数据结构,现在生活当中的使用我们就能看的出来,可能我们并不需要它的底层构造但是我们要学习一个语
言. 最快的途径就是大师写出来的代码,手头都是资料我们要学习别人的巧妙的地方. 多看源码多多构造经典的算法,或者容器.
尝试自己编写代码,理解那个框架, 这样对我们的进步都是非常有用的.红黑树目前我就总结这么多,哪里有不足欢迎大家来指出来
,我会虚心改正.
所有代码实现:
#include<iostream>
#include<Windows.h>
#include<assert.h>
using namespace std;
enum colour
{
RED,
BLACK
};
template<class K, class V>
struct RBTreeNode
{
K _key;
K _val;
RBTreeNode<K, V>* _left;
RBTreeNode<K, V>* _right;
RBTreeNode<K, V>* _parent;
colour _col;
RBTreeNode(const K& key, const V& val)
:_key(key)
, _val(val)
, _left(NULL)
, _right(NULL)
, _parent(NULL)
, _col(RED)
{}
};
template<class K, class V>
class RBTree
{
typedef RBTreeNode<K, V> Node;
public:
RBTree()
:_root(NULL)
{}
bool Insert(const K& key, const V& val)
{
//_Insert(_root, x, y);
if (_root == NULL)
{
_root = new Node(key, val);
_root->_col = BLACK;
}
Node* cur = _root;
Node* parent = cur;
while (cur)
{
if (cur->_key > key)
{
parent = cur;
cur = cur->_left;
}
else if (cur->_key < key)
{
parent = cur;
cur = cur->_right;
}
else if (cur->_key == key)
{
return true;
}
}
if (parent->_key > key)
{
parent->_left = new Node(key, val);
parent->_left->_parent = parent;
cur = parent->_left;
}
else
{
parent->_right = new Node(key, val);
parent->_right->_parent = parent;
cur = parent->_right;
}
//目前父亲节点,插入节点,叔叔节点已经就绪.
while(parent && parent->_col == RED)
{
Node* parentparent = parent->_parent;
Node* uncle = NULL;
if (parentparent->_left == parent)
uncle = parentparent->_right;
else
uncle = parentparent->_left;
if(uncle && uncle->_col == RED)
{
parentparent->_col = RED;
parent->_col = BLACK;
uncle->_col = BLACK;
cur = parentparent;
parent = cur->_parent;
}
else if (uncle == NULL || uncle->_col == BLACK)
{
if (parentparent->_left == parent)
{
if (parent->_left == cur)
{
RotateR(parentparent);
parent->_col = BLACK;
}
else
{
RotateLR(parentparent);
cur->_col = BLACK;
}
}
else
{
if (parent->_right == cur)
{
RotateL(parentparent);
parent->_col = BLACK;
}
else
{
RotateRL(parentparent);
cur->_col = BLACK;
}
}
parentparent->_col = RED;
if (parentparent == _root)
{
_root = parent;
}
}
else
{
assert(false);
}
if (_root->_col == RED)
{
_root->_col = BLACK;
}
}
return false;
}
bool ISRBtree()
{
if (_root->_col == RED)
{
return false;
}
size_t n = 0;
size_t m = 0;
Node* cur = _root;
while (cur)
{
if (cur->_col == BLACK)
{
n++;
}
cur = cur->_left;
}
return _ISRBtree(_root, m, n);
}
void print()
{
_print(_root);
}
protected:
void _print(Node* root)
{
if (root == NULL)
return;
_print(root->_left);
cout << root->_val << " ";
_print(root->_right);
}
bool _ISRBtree(Node* root, size_t m, size_t n)
{
if (root == NULL)
{
if (m == n)
return true;
else
return false;
}
if (root->_col == BLACK)
{
m++;
}
if (root->_col == RED && root->_parent && root->_parent->_col == RED)
{
return false;
}
return _ISRBtree(root->_left, m, n) && _ISRBtree(root->_right, m, n);
}
void RotateLR(Node*& parent)
{
RotateL(parent->_left);
RotateR(parent);
}
void RotateRL(Node*& parent)
{
RotateR(parent->_right);
RotateL(parent);
}
void RotateR(Node*& parent)
{
Node* subL = parent->_left;
Node* subLR = NULL;
if (subL)
subLR = subL->_right;
parent->_left = subLR;
if (subLR)
subLR->_parent = parent;
Node* ppNode = parent->_parent;
subL->_right = parent;
parent->_parent = subL;
if (ppNode == NULL)
{
_root = subL;
_root->_parent = NULL;
}
else
{
if (ppNode->_left == parent)
ppNode->_left = subL;
else
ppNode->_right = subL;
subL->_parent = ppNode;
}
}
void RotateL(Node*& parent)
{
Node* subR = parent->_right;
Node* subRL = NULL;
if (subR)
subRL = subR->_left;
parent->_right = subRL;
if (subRL)
subRL->_parent = parent;
Node* ppNode = parent->_parent;
subR->_left = parent;
parent->_parent = subR;
if (ppNode == NULL)
{
_root = subR;
_root->_parent = NULL;
}
else
{
if (ppNode->_left == parent)
ppNode->_left = subR;
else
ppNode->_right = subR;
subR->_parent = ppNode;
}
}
private:
Node* _root;
};
void Test()
{
RBTree<int, int> T;
//8 9 2 4 1 6 3 5
T.Insert(8, 8);
T.Insert(9, 9);
T.Insert(2, 2);
T.Insert(4, 4);
T.Insert(1, 1);
T.Insert(6, 6);
T.Insert(3, 3);
T.Insert(5, 5);
cout << "该二叉树是否为红黑树??" << T.ISRBtree() << endl;
T.print();
system("pause");
}