紅黑樹也是一種而叉搜索樹,因此二叉搜索樹的性質紅黑樹都具有,同時,我們知道爲了避免最壞情況下的二叉搜索樹(就是高度不平衡的情況)衍生出了AVL樹,使其任何節點的左右子樹的高度差相差最多1,從而達到平衡,以確保最壞情況下的搜索效率。當然紅黑樹爲了比較好的搜索效率降低了對平衡的要求,但是紅黑樹仍然具有良好的平衡狀態。
AVL樹與RB_tree
AVL樹也稱爲高度平衡樹,其插入,刪除,查找在平均和最壞情況下都是O(log n),增加和刪除要通過一次或多次樹的旋轉來重新平衡這個樹。
RB_tree並不追求完全平衡,只要求部分達到平衡要求,降低了對旋轉的要求,從而提高了性能,紅黑樹能夠以O(log 2 n)的時間複雜度進行插入,刪除,查找,此外由於它的設計任何不平衡都會在3次旋轉之內解決。相比較而言紅黑樹和AVL樹的算法時間複雜度相同,但統計性能比AVL樹高。同時,紅黑樹的應用比AVL樹廣泛
例如:(1)紅黑樹廣泛應用於c++的STL中,比如關聯式容器set, map,multiset, multimap都以RB_tree爲底層機制。
(2)epoll在內核中的實現,用紅黑樹管理事件塊。
(3)linux進程調度上,用紅黑樹管理進程控制塊。
(4)nginx中用紅黑樹管理timer
下面自己分析了SGI中的stl_tree.h源碼的分析
#ifndef __SGI_STL_INTERNAL_TREE_H
#define __SGI_STL_INTERNAL_TREE_H
//RB-tree的節點設計
//設計思路節點設計分爲兩層__rb_tree_node繼承__rb_tree_node_base以達到將指針和數據分開
typedef bool __rb_tree_color_type;
const __rb_tree_color_type __rb_tree_red = false;
const __rb_tree_color_type __rb_tree_black = true;
struct __rb_tree_node_base
{
typedef __rb_tree_color_type color_type;
typedef __rb_tree_node_base* base_ptr;
color_type color;
base_ptr parent;
base_ptr left;
base_ptr right;
//找到存儲的最小值
static base_ptr minimum(base_ptr x)
{
wile(x->left != 0){
x = x->left;
}
return x;
}
static base_ptr maximum(base_ptr x)
{
while(x->right != 0){
x = x->right;
}
return x;
}
};
template<class Value>
struct __rb_tree_node : public __rb_tree_node_base
{
typedef __rb_tree_node<Value>* link_type;
Value value_field;
};
//因爲紅黑樹是非線性的結構,所以要找到一個節點的前面的節點或者後面的節點比較麻煩,且紅黑樹節點的顯示是
//按中序排列的,所以對迭代器的前進和後退操作要借用內置函數increment()和decrement()
//RB_tree迭代器結構設計,也是採用雙層迭代其結構
struct __rb_base_iterator
{
typedef __rb_tree_node_base::base_ptr base_ptr;
typedef bidirectional_iterator_tag iterator_category;
typedef ptrdiff_t difference_type;
base_ptr node;
//迭代器的前進操作operator++()調用了基層迭代器的increment()
//(1)如果node有右子樹,但這個右子樹沒有左子節點,那麼node前進一個節點爲node->right.如果這個右子 樹有左子樹,那麼node後面的節點就是這個左子樹的最左邊的那個節點。
//(2)如果node沒有右子樹,並且node是node->parent的左子樹,那麼node後面的節點是node->parent。如果node是node->parent的右子樹,則一直上朔,直到不再是右子節點比如爲y,那麼node後面的節點是就是y->parent這個節點
void increment()
{
if(node->right != 0){
node = node->right;
while(node->left != 0){
node = node->left;
}
}
else{
base_ptr y = node->parent;
while(node == y->right){
node = y;
y = y->parent;
}
if(node->right != y){
node = y;
}
}
}
//迭代器的後退操作operator--()調用基層迭代器ecrement()
//(1)node有左子樹,且node的左子樹沒有右子樹,那麼node前面的節點就是node->left。如果node的左子樹有右子樹,那麼node前面的節點就是這個右子樹的最右邊的節點。
//(2)node沒有左子樹,且node爲其父節點的左節點,那麼就上朔直到node不爲node->parent的左節點,那麼node的前面的節點就是這個node->parent。如果爲其父節點的右節點,那麼node的前面的節點就是node->parent。
void decrement()
{
//判斷node就是header這個虛節點
if(node->color == __rb_tree_red && node->parent->parent == node){
node = node->right;
}
else if(node->left != 0){
base_ptr y = node->left;
while(y->right != 0){
y = y->right;
}
node = y;
}
else{
base_ptr y = node->parent;
while(node == y->left){
node = y;
y = y->parent;
}
node = y;
}
}
};
template<calss Value, class Ref, class Ptr>
struct __ rb_tree_iterator : public __rb_tree_base_iterator
{
typedef Value value_type;
typedef Ref reference;
typedef Ptr pointer;
typedef __rb_tree_iterator<Value, Value&, Value*> iterator;
typedef __rb_tree_iterator<Value, const Value&, const Value*> const_iterator;
typedef __rb_tree_iterator<Value, Ref, Ptr> self;
typedef __rb_tree_node<Value>* link_type;
__rb_tree_iterator(){}
__rb_tree_iterator(link_type x){node = x;}
__rb_tree_iterator(const iterator& it){ode = it.node;}
self& operator++() { increment(); return *this; }
self operator++(int) {
self tmp = *this;
increment();
return tmp;
}
self& operator--() { decrement(); return *this; }
self operator--(int) {
self tmp = *this;
decrement();
return tmp;
}
};
inline bool operator==(const __rb_tree_base_iterator& x,
const __rb_tree_base_iterator& y)
{
return x.node == y.node;
}
inline bool operator!=(const __rb_tree_base_iterator& x,
const __rb_tree_base_iterator& y)
{
return x.node != y.node;
}
//RB_tree數據結構
template <class Key, class Value, class KeyOfValue, class Compare,
class Alloc = alloc>
class rb_tree {
protected:
typedef void* void_pointer;
typedef __rb_tree_node_base* base_ptr;
typedef __rb_tree_node<Value> rb_tree_node;
typedef simple_alloc<rb_tree_node, Alloc> rb_tree_node_allocator;
typedef __rb_tree_color_type color_type;
public:
typedef Key key_type;
typedef Value value_type;
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef rb_tree_node* link_type;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
public:
rb_tree(const Compare& comp = Compare())
: node_count(0), key_compare(comp) { init(); }
~rb_tree() {
clear();
put_node(header);
}
rb_tree<Key, Value, KeyOfValue, Compare, Alloc>&
operator=(const rb_tree<Key, Value, KeyOfValue, Compare, Alloc>& x);
protected:
get_node(){return rb_tree_node_allocator::allocate();}
void put_node(link_type p) { rb_tree_node_allocator::deallocate(p); }
link_type create_node(const value_type& x) {
link_type tmp = get_node();
put_node(tmp);
return tmp;
}
//複製一個節點
link_type clone_node(link_type x) {
link_type tmp = create_node(x->value_field);
tmp->color = x->color;
tmp->left = 0;
tmp->right = 0;
return tmp;
}
void destroy_node(link_type p) {
destroy(&p->value_field);
put_node(p);
}
protected:
size_type node_count; // keeps track of size of tree
link_type header;
Compare key_compare;
//這三個函數方便取得header的成員
link_type& root() const { return (link_type&) header->parent; }
//取得最左邊的節點
link_type& leftmost() const { return (link_type&) header->left; }
//取得最右邊的節點
link_type& rightmost() const { return (link_type&) header->right; }
//這六個函數方便取得節點x的成員(自身做參數)自己對這12個函數沒有具體搞明白爲什麼寫兩種
static link_type& left(link_type x) { return (link_type&)(x->left); }
static link_type& right(link_type x) { return (link_type&)(x->right); }
static link_type& parent(link_type x) { return (link_type&)(x->parent); }
static reference value(link_type x) { return x->value_field; }
static const Key& key(link_type x) { return KeyOfValue()(value(x)); }
static color_type& color(link_type x) { return (color_type&)(x->color); }
//這六個函數方便取得節點x的成員(以父類類型的節點做參數)
static link_type& left(base_ptr x) { return (link_type&)(x->left); }
static link_type& right(base_ptr x) { return (link_type&)(x->right); }
static link_type& parent(base_ptr x) { return (link_type&)(x->parent); }
static reference value(base_ptr x) { return ((link_type)x)->value_field; }
static const Key& key(base_ptr x) { return KeyOfValue()(value(link_type(x)));}
static color_type& color(base_ptr x) { return (color_type&)(link_type(x)->color); }
static link_type minimum(link_type x) {
return (link_type) __rb_tree_node_base::minimum(x);
}
static link_type maximum(link_type x) {
return (link_type) __rb_tree_node_base::maximum(x);
}
public:
typedef __rb_tree_iterator<value_type, reference, pointer> iterator;
typedef __rb_tree_iterator<value_type, const_reference, const_pointer>
const_iterator;
public:
Compare key_comp()const {return key_compare;}
iterator begin(){return leftmost;}
//最後的一個節點應該是rightmost但是end()指向的是最後節點的後一個節點自然就是header
iterator end(){return header;}
bool empty()const{return node_count == 0;}
size_type size()const{return node_count;}
size_type max_size()const{return size_type(-1);}
public:
pair<iterator, bool>insert_unique(const value_type& x);
iterator insert_equal(const value_type& x);
iterator insert_unique(iterator position, const value_type& x);
iterator insert_equal(iterator position, const value_type& x);
};
//這裏的返回值是個RB_tree迭代器,所以前面加那麼多
template<class Key, class Value, class KeyOfValue, class Compare, class Alloc>
typename rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::iterator
rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::insert_equal(const value& v)
{
link_type y = header;
link_type x = root();
while(x != 0){
y = x;
x = key_compare(KetOfValue()(v), key(x)) ? left(x):right(x);
}
//x爲新插入節點,Y爲插入的父節點,v爲插入的新值
return __insert(x, y, v);
}
template<class Key, class Value, class KeyOfValue, class Compare, class Alloc>
//注意這一行,返回值是pair類型,pair稱爲對組,這樣寫則返回值不返回一個值,而是返回兩個值,這裏可以看出返回的
//第一個值是iterator類型,即返回插入點的位置。返回的第二個值是bool類型,通過true或者false來判斷插入是否成功
pair<typename rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::iterator, bool>
rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::insert_unique(const value_type& v)
{
link_type y = header;
link_type x = root();
bool comp = true;
//從根節點開始查找適當的插入點
while(x != 0){
y = x;
comp = key_compare(KeyOfValue()(v), key(y));
//當插入的元素v<找到的插入點即y,則v往y的左邊插入,否則右邊
x = comp ? left(x) : right(x);
}
//這裏大家要注意理解,畫圖可以最直觀的分析,這裏自己也是看了好久才弄明白
//下面的代碼的作用是防止插入值重複。
//分兩種情況
//(1)如果插入點的父節點是樹的最左邊節點,那麼直接插入
//(2)如果插入點的父節點不是樹的最左邊的節點,這個時候要考慮到插入的新節點
// 是否可能跟已經插入的節點值重複,因此要進行回朔
iterator j = iterator(y);
//if(com)爲真,也就是說當v<y,往左節點插入新值
if(comp){
if(j === begin()){
return pair<iterator, bool>(__insert(x, y, v), true);
}else{
--j;
}
}
//滿足這個條件即表示新插入的鍵值不與已經插入的節點的鍵值相等
if(key_compare(key(j.node), KeyOfValue()(v))){
return pair<iterator, bool>(__insert(x, y, v), true);
}
//鍵值重複不進行插入操作
return pair<iterator, bool>(__insert(j, false);
}
template<class Key, class Value, class KeyOfValue, class Compare, class Alloc>
typename rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::iterator
rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::__insert(base_ptr x_, base_type y_, const value_type& v)
{
link_type x = (link_type)x_;
link_type y = (link_type)y_;
link_type z;
//當key_compare(KeyOfValue()(v), keyy(y))爲真時,也就是說v<y,往y的左節點插入,分3種情況
//(1)y==header,插入的節點是root,這樣就要注意要讓root()=插入的節點,並且讓header的左指針指向插入節點
//即leftmost()=z
//(2)y==leftmost,插入的地方是樹的最左邊的節點,注意的是要讓header的左指針指向這個插入節點即leftmost()=z
//(3)插入的僅僅是個普通的節點,直接讓父節點y的左指針指向這個插入的節點即可
if(y == header || x != 0 || key_compare(KeyOfValue()(v), key(y))){
z = create_node(v);
//讓leftmost() = z
left(y) = z;
//如果插入的節點是root節點,則讓root作爲header的左子節點
if(y == header){
root() = z;
rightmost = z;
//如果插入的地方是樹的最左邊的節點
}else if(y == leftmost()){
leftmost() = z;
}
}
//當key_compare(KeyOfValue()(v), key(y))爲假時,也就是說v>y,(注意這裏規定的默認的key_compare規則是小與)
//往插入點的父節點y的右節點插入,分1種情況
//這裏不用判斷插入點爲root節點,因爲規定root節點只能作爲header的左子節點插入
else{
z = create_node(v);
right(y) = z;
if(y == rightmost()){
rightmost() = z;
}
}
//設置新插入節點的父節點和左右節點
parent(z) = y;
left(z) = 0;
right(z) = 0;
//插入節點後記得要重新調整平衡和顏色
__rb_tree_rebalance(z, header->parent);
++node_count;
return iteratro(z);
}
//紅黑樹的旋轉以及顏色的調整比較麻煩,所以大家要靜下心來
//一:當插入點的父節點爲祖父節點的左子樹:
// (1)如果伯父節點存在且爲紅
// (2)如果伯父節點不存在或者爲黑,
// (1)則又要判斷插入節點爲父節點的左子樹
// (2)插入節點爲父節點的右子樹
//二:當插入點的父節點爲祖父節點的右子樹
// (1)如果伯父節點存在且爲紅
// (2)如果伯父節點不存在或者爲黑
// (1)插入點爲父節點的左子樹
// (2)插入點爲父節點的右子樹
inline void __rb_tree_rebalance(__rb_tree_node_base* x, __rb_tree_node_base*& root)
{
//新插入的節點必須爲紅節點,因爲如果插入的新節點爲黑節點,這樣就打破了紅黑樹的約束條件
//紅黑樹要求任一節點到NULL的任何的路徑,所含之黑節點數目必須相等
x->color = rb_tree_red;
while(x != root && x->parent->color == rb_tree_red){
//插入的父節點爲祖父節點的左子樹
if(x->parent == x->parent->parent->left){
//伯父節點存在且爲紅
__rb_tree_node_base* y = x->parent->parent->right;
if(y && y->color == __rb_tree_red){
x->parent->color = __rb_tree_black;
y->color = __rb_tree_black;
x->parent->parent = __rb_tree_red;
x = x->parent->parent;
}
//伯父節點不存在或者爲黑
else{
if(x == x->parent->right){
x = x->parent;
__rb_tree_rotate_left(x, root);
}
x->parent->color = __rb_tree_black;
x->parent->parent->color = __rb_tree_red;
__rb_tree_rotate_right(x->parent->parent, root);
}
}
//插入的節點的父節點爲祖父節點的右子樹
else{
//伯父節點存在且爲紅
__rb_tree_node_base* y =x->parent->parent->left;
if(y && y->color == __rb_tree_red){
x->parent->color = __rb_tree_black;
y->color = __rb_tree_black;
x->parent->parent->color = __rb_tree_red;
x = x->parent->parent;
}
//伯父節點不存在或者爲黑
else{
if(x == x->parent->left){
x = x->parent;
__rb_tree_rotate_right(x, root);
}
x->parent->color = __rb_tree_black;
x->parent->parent->color = __rb_tree_red;
__rb_tree_rotate_left(x->parent->parent, root);
}
}
}
//根節點永遠爲黑
root->color = __rb_tree_black;
}
//下面兩個函數是紅黑樹節點的旋轉
//x爲旋轉對象
//紅黑樹的旋轉根AVL樹的旋轉一樣,只是由於紅黑樹的節點又parent這個指針,所以旋轉的時後要特別的注意這個指針的連接
//左旋:
//(1)將旋轉目標x的右子節點Y的左子樹掛在x的右子樹上,
//(2)將y樹掛在x的父節點上,
//(3)將y的左指針指向x;
//
inline void __rb_tree_rotate_left(__rb_tree_node_base* x, __rb_tree_node_base*& root)
{
__rb_tree_node_base* y = x->right;
x->right = y->left;
if(y->left != 0){
y->left->parent = x;
}
y->parent = x->parent;
if(x == root){
root = y;
}
else if(x == x->parent->left){
x->parent->left = y;
}
else{
x->parent->right = y;
}
y->left = x;
x->parent = y;
}
//右旋:
//(1)將旋轉目標x的左子樹y的右子樹掛在x的左鏈上
//(2)將y樹掛在x的父節點上
//(3)將x樹掛在y的右鏈上
inline void __rb_tree_rotate_right(__rb_tree_node_base* x, __rb_tree_node_base*& root)
{
__rb_tree_node_base* y = x->right;
x->left = y->right;
if(y->right != 0){
y->right->parent = x;
}
y->parent = x->parent;
if(x == root){
root = y;
}
else if(x == x->parent->left){
x->parent->left = y;
}else{
x->parent->right = y;
}
y->right = x;
x->parent = y;
}
};
#endif
/