彻底搞懂红黑树(二)
其实关于红黑树,STL源码剖析---红黑树原理详解 已经写得非常好了。但套用新警察故事里的谢霆锋说的一句话:自己查,印象深一点。这里也是一样,在自己写,印象深一点。如果你要看正宗的STL源码剖析---红黑树原理详解,那请你点击这个。这里的是D版的o(╯□╰)o 当然,我也会加一些我自己的理解,因为大神写文章都比较精简,而我这是写给我自己看的,有一点口水话加深点印象。
三 红黑树的插入
红黑树的节点插入默认是节点为红色的。我自己理解是,其实插入红还是黑都可以,但就要看后面的调整是否麻烦。
插入黑点,会增加路径上黑点的数目,一定会破坏性质5
插入红点:
当其父节点为黑色时,不影响平衡,继续保持红黑性质
当其父节点为红色时,可能破坏性质2(根节点是黑色的)、性质4(红色节点的子节点一定是黑色节点),需要进行修正。
因为第一篇文章已经说了,黑节点至少是红节点的两倍,这说明插入红节点OK的概率高很多(因为父节点为黑,插入子节点为红色就不会和性质冲突),这样插入就省事多了,嘿嘿,这也是红黑树为什么战胜AVL树的原因之一,插入效率高啊,节点贴上去就ok了,都不用什么左转右转调整了,多省事啊;再说,如果插入子节点为黑色,o(╯□╰)o了,黑高度变化了,得调整,如果每次都插入黑节点,都得调整,没事闲的蛋疼啊。。。
红黑树插入分一下几种情况:
1、黑父
如下图所示,如果新节点的父结点为黑色结点,那么插入一个红点将不会影响红黑树的平衡,此时插入操作完成。红黑树比AVL树优秀的地方之一在于黑父的情况比较常见,从而使红黑树需要旋转的几率相对AVL树来说会少一些。(大神和我的理解差不多,不过别人的精简很多,我的就是口水话。)

如果新节点的父结点为红色,这时就需要进行一系列操作以保证整棵树红黑性质。如下图所示,由于父结点为红色,此时可以判定,祖父结点必定为黑色。这时需要根据叔父结点的颜色来决定做什么样的操作。青色结点表示颜色未知。由于有可能需要根结点到新点的路径上进行多次旋转操作,而每次进行不平衡判断的起始点(我们可将其视为新点)都不一样。所以我们在此使用一个蓝色箭头指向这个起始点,并称之为判定点。

当叔父结点为红色时,如下图所示,无需进行旋转操作,只要将父和叔结点变为黑色,将祖父结点变为红色即可。但由于祖父结点的父结点有可能为红色,从而违反红黑树性质。此时必须将祖父结点作为新的判定点继续向上(迭代)进行平衡操作。(注意这里是需要迭代的,有可能会调整到根节点)

2.2 黑叔
当叔父结点为黑色时,需要进行旋转,以下图示了所有的旋转可能:(case1 和caes 2 都是把左边较大的节点调整到上面去)
Case 1:

Case 2:



Case 4:

有了上面的分析,红黑树的插入就好理解多了,代码也容易读懂。不过不是很喜欢c++的代码,有时间了把linux内核的红黑树源码贴出来。这里还是贴的大神注视的红黑树的插入操作源代码:
自己写的红黑树代码参考其他书籍中的描述(代码有错有时间更改大题思路如下)
#ifndef _REDBLACKTREE_
#define _REDBLACKTREE_
static const int red = 0;
static const int black = 1;
template <typename T>
class RedBlackTree;
template <typename T>
class RedBlackNode
{
public:
RedBlackNode(const T &element = T(), RedBlackNode *lt = NULL, RedBlackNode*rt = NULL,int mcolor = red) :ement(element), left(lt), right(rt), color(mcolor){}
private:
RedBlackNode<T> *left;
RedBlackNode<T> *right;
T ement;
int color;
friend class RedBlackTree<T>;
};
template <typename T>
class RedBlackTree
{
public:
typedef RedBlackNode<T> Node;
RedBlackTree(const T &neglnf = T());
~RedBlackTree();
void insert(const T &data);
void RotateWitthRightChild_s(Node * &k2);
void RotateWitthRightChild();
void RotateWitthLeftChild_s(Node * &k2);
void RotateWitthLeftChild();
void doubleRotateWitthRightChild_s(Node *&k2);
void doubleRotateWitthRightChild();
void doubleRotateWitthLeftChild_s(Node *&k2);
void doubleRotateWitthLeftChild();
void HandleReorient(const T &item);
RedBlackNode<T> *rotate(const T&item, Node *parent);
void PerOrder();
void PerOrder_s( Node* node);
T& Root();
private:
Node *head;//指向红黑树的头
Node *nullnode;//空节点
Node *current;//指向当前节点
Node *parent;//父节点
Node *grand;//祖父节点;
Node *great;//曾祖父节点
};
template<typename T>
RedBlackTree<T>::RedBlackTree(const T &neglnf = T())
{
nullnode = new Node();
nullnode->left = nullnode->right = nullnode;
head = new Node(neglnf);
head->left = head->right = nullnode;
}
template<typename T>
void RedBlackTree<T>::PerOrder_s(Node* node)
{
if (node == nullnode)
{
return;
}
PerOrder_s(node->left);
cout << node->ement << endl;
PerOrder_s(node->right);
}
template<typename T>
void RedBlackTree<T>::PerOrder()
{
PerOrder_s(head->right);
}
template<typename T>
T& RedBlackTree<T>::Root()
{
return head->right->ement;
}
template<typename T>
RedBlackTree<T>::~RedBlackTree()
{
delete head;
delete nullnode;
}
template<typename T>
void RedBlackTree<T>::insert(const T &data)
{
current = parent = grand = head;
nullnode->ement = data;
while (current->ement != data)
{
great = grand;
grand = parent;
parent = current;
current = (data < current->ement) ? current->left : current->right;
if (current->left->color == red&¤t->right->color == red)
{
HandleReorient(data);
}
}
if (current != nullnode)
{
throw "erro";
}
current = new Node(data, nullnode, nullnode);
if (data < parent->ement)
{
parent->left = current;
}
else
{
parent->right = current;
}//自动平衡-》旋转左转和 右转进行红黑树旋转
HandleReorient(data);//插入的时候后进行调整;
}
template<typename T>
void RedBlackTree<T>::RotateWitthRightChild_s(Node *&node)
{
Node* mleft = node->left;
node->left = mleft->right;
mleft->right = node;
node = mleft;//用该地址覆盖掉原来的node根
}
template<typename T>
void RedBlackTree<T>::RotateWitthRightChild()
{
RotateWitthRightChild_s(head->right);
}
template<typename T>
void RedBlackTree<T>::RotateWitthLeftChild()
{
RotateWitthLeftChild_s(head->right);
}
template<typename T>
void RedBlackTree<T>::RotateWitthLeftChild_s(Node *&node)
{
Node* mright = node->right;
node->right = mright->left;
mright->left = node;
node = mright;
}
template<typename T>
void RedBlackTree<T>::doubleRotateWitthRightChild_s(Node *&node)//
{
//两次单转 第一次向右第二次向左
RotateWitthRightChild_s(node->left);//先左转
RotateWitthLeftChild_s(node);//在右转
}
template<typename T>
void RedBlackTree<T>::doubleRotateWitthRightChild()//带着做孩子啊向右转
{
doubleRotateWitthRightChild_s(head->right->left);
}
template<typename T>
void RedBlackTree<T>::doubleRotateWitthLeftChild_s(Node *&node)
{
RotateWitthRightChild_s(node);
RotateWitthLeftChild_s(node->left);//先右转在左转
}
template<typename T>
void RedBlackTree<T>::doubleRotateWitthLeftChild()
{
doubleRotateWitthLeftChild_s(head->right->left);
}
template<typename T>
void RedBlackTree<T>::HandleReorient(const T & item)
{
current->color = red;
current->left->color = current->right->color = red;
if (parent->color == red)
{
grand->color = red;
if (item < grand->ement != item < parent->ement)//判断是不是内部孙子
{
parent = rotate(item, grand);
}
else
{
current = rotate(item,great);
}
current->color = black;
}
head->right->color = black;
}
template <typename T>
RedBlackNode<T>* RedBlackTree<T>::rotate(const T &item, Node *parent)
{
if (item < parent->ement)
{
if (item < parent->left->ement)
RotateWitthLeftChild_s(parent->left);
RotateWitthRightChild_s(parent->left);
return parent->left;
}
else
{
if (item < parent->right->ement)
{
RotateWitthLeftChild_s(parent->right);
}
else
{
RotateWitthRightChild_s(parent->right);
}
return parent->right;
}
}
#endif