红黑树性质:
1、每个节点不是黑色就是红色
2、根节点为黑色
3、节点为红色,其子节点必须为黑色(新增节点之父必须为黑)
4 、任一节点至NULL(树尾端)的任何路径,所含的黑节点必须相同。(新增节点必须为红)
RB-Tree的设计也采用了两层架构,以下是节点设计:
typedef bool __rb_tree_color_type; const __rb_tree_color_type __rb_tree_red = false; // 红色为0 const __rb_tree_color_type __rb_tree_black = true; // 黑色为1 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) { while (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; //节点的值 };
迭代器设计:
RB-Tree的迭代器属于双向迭代器,其中迭代器的前进及后退操作是调用了基层迭代器increment(),decrement(),如下是基层迭代器:
//迭代器基类,类型为bidirectional_iterator_tag,可以双向移动 struct __rb_tree_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; //下面只是为了实现oprerator++的,其他地方不会调用了。 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; } /* 若此时的右子节点不等于此时的父节点,此时的父节点即为解答,否则此时的node为解答. 这样做是为了应付一种特殊情况:我们欲寻找根节点的下一个节点。而恰巧根节点无右孩子。 当然,以上特殊做法必须配合RB-tree根节点与特殊header之间的特殊关系,在上面有图 */ if (node->right != y) // 若此时的右子节点不等于此时的父节点 node = y; // 此时的父节点即为解答 // 否则此时的node为解答 } } //查找前驱结点。 void decrement() { if (node->color == __rb_tree_red && // 如果是红节点,且 node->parent->parent == node) // 父节点的父节点等于自己 node = node->right; // 状况(1) 右子节点即为解答。 /* 以上情况发生于node为header时(亦即node为end()时)。注意,header之右孩子即 mostright,指向整棵树的max节点。上面有图 */ //左子树的最大值结点 else if (node->left != 0) { base_ptr y = node->left; while (y->right != 0) y = y->right; node = y; } /* 既非根节点,且无左子树。找其最低祖先节点y,且y的右孩子也是其祖先节点 */ else { base_ptr y = node->parent; //找出父节点 while (node == y->left) { node = y; y = y->parent; } node = y; } } };
本来只有root节点,但处理时不方便,每到边界处还得再处理,所以为根节点增加一个父节点header,使header和root互为对方的父节点。
下面是RB-Tree的正规迭代器
template <class 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) { node = it.node; } //重载操作符 reference operator*() const { return link_type(node)->value_field; } #ifndef __SGI_STL_NO_ARROW_OPERATOR pointer operator->() const { return &(operator*()); } #endif /* __SGI_STL_NO_ARROW_OPERATOR */ //调用了increment() self& operator++() { increment(); return *this; } self operator++(int) { self tmp = *this; increment(); return tmp; } //调用了decrement self& operator--() { decrement(); return *this; } self operator--(int) { self tmp = *this; decrement(); return tmp; } };
RB-Tree的insert_unique()和insert_equal()是两种主要的插入操作
// 安插新值;允许键值重复。返回新插入节点的迭代器 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(KeyOfValue()(v), key(x)) ? left(x) : right(x); } return __insert(x, y, v); } /* 不允许键值重复,否则安插无效。 返回值是个pair,第一个元素是个RB-tree迭代器,指向新增节点。 第二个元素表示安插是否成功。 */ template <class Key, class Value, class KeyOfValue, class Compare, class Alloc> pair<typename rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::iterator, bool> rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::insert_unique(const Value& v) { link_type y = header; link_type x = root(); //从根节点开始 bool comp = true; while (x != 0) { // 从根节点开始向下寻找适当安插位置 y = x; comp = key_compare(KeyOfValue()(v), key(x)); // v 键值小于目前节点的键值? x = comp ? left(x) : right(x); // 遇「大」往左,遇「小于或等于」往右 } //离开while循环之后,y所指即为安插点的父节点,x必为叶子节点 iterator j = iterator(y); // 令迭代器j指向安插点之父节点 y if (comp) //如果离开while循环时comp为真,表示 父节点键值>v ,将安插在左孩子处 if (j == begin()) // 如果j是最左节点 return pair<iterator,bool>(__insert(x, y, v), true); // 以上,x 为安插点,y 为安插点之父节点,v 为新值。 else // 否则(安插点之父节点不是最左节点) --j; // 调整 j,回头准备测试... if (key_compare(key(j.node), KeyOfValue()(v))) // 小于新值(表示遇「小」,将安插于右侧) return pair<iterator,bool>(__insert(x, y, v), true); //若运行到这里,表示键值有重复,不应该插入 return pair<iterator,bool>(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_ptr y_, const Value& v) { //参数x_为新值安插点,参数y_为安插点之父节点,参数v 为新值 link_type x = (link_type) x_; link_type y = (link_type) y_; link_type z; //key_compare是键值得比较准则,是个函数或函数指针 if (y == header || x != 0 || key_compare(KeyOfValue()(v), key(y))) { z = create_node(v); // 产生一个新节点 left(y) = z; // 这使得当y为header时,leftmost()=z if (y == header) { root() = z; rightmost() = z; } else if (y == leftmost()) // 如果y为最左节点 leftmost() = z; // 维护leftmost(),使它永远指向最左节点 } else { z = create_node(v); right(y) = z; // 令新节点成为安插点之父节点y的右孩子 if (y == rightmost()) rightmost() = z; // 维护rightmost(),使它永远指向最右节点 } parent(z) = y; // 设定新节点的父节点 left(z) = 0; // 设定新孩子节点的左孩子 right(z) = 0; // 设定新孩子节点的右孩子 // 新节点的颜色将在 __rb_tree_rebalance() 设定并调整 __rb_tree_rebalance(z, header->parent); // 参数一为新增节点,参数二为root ++node_count; // 节点数增加 return iterator(z); // 返回迭代器,指向新增节点 }
作为平衡树,最重要的是调节保持平衡,如下几个函数:
//左旋转 inline void __rb_tree_rotate_left(__rb_tree_node_base* x, __rb_tree_node_base*& root) { // x 为旋转点 __rb_tree_node_base* y = x->right; // y为x的右孩子 x->right = y->left; if (y->left !=0) y->left->parent = x; // 不要忘了回马枪设置父节点 y->parent = x->parent; // 令 y 完全顶替 x 的地位(必须将x对其父节点的关系完全接收过来) if (x == root) // x 为根节点 root = y; else if (x == x->parent->left) // x 为父节点的左孩子 x->parent->left = y; else // x 为父节点的右孩子 x->parent->right = y; y->left = x; x->parent = y; } //右旋转 inline void __rb_tree_rotate_right(__rb_tree_node_base* x, __rb_tree_node_base*& root) { // x 为旋转点 __rb_tree_node_base* y = x->left; // y x的左孩子 x->left = y->right; if (y->right != 0) y->right->parent = x; // 別忘了回马枪设置父节点 y->parent = x->parent; // 令 y 完全顶替 x 的地位(必须将x对其父节点的关系完全接收过来) if (x == root) // x 为根节点 root = y; else if (x == x->parent->right) // x 为父节点的右孩子 x->parent->right = y; else // x 为父节点的左孩子 x->parent->left = y; y->right = x; x->parent = y; } //重新令RB-tree平衡(改变颜色和旋转)参数x为新增节点,参数二为root节点 inline void __rb_tree_rebalance(__rb_tree_node_base* x, __rb_tree_node_base*& root) { 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; // 令y 为伯父节点 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 { // 无伯父节点或伯父节点为黑色(NULL就是黑色) 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; // y为伯父节点 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 { // 无伯父节点或伯父节点为黑色(NULL就是黑色) 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); // 第一个参数做旋转 } } } // while 結束 root->color = __rb_tree_black; // 根节点永远为黑色 } //删除结点z inline __rb_tree_node_base* __rb_tree_rebalance_for_erase(__rb_tree_node_base* z, __rb_tree_node_base*& root, __rb_tree_node_base*& leftmost, __rb_tree_node_base*& rightmost) { __rb_tree_node_base* y = z; __rb_tree_node_base* x = 0; __rb_tree_node_base* x_parent = 0; if (y->left == 0) // z has at most one non-null child. y == z. x = y->right; // x might be null. else if (y->right == 0) // z has exactly one non-null child. y == z. x = y->left; // x is not null. else { // z has two non-null children. Set y to y = y->right; // z's successor. x might be null. while (y->left != 0) y = y->left; x = y->right; } if (y != z) { // relink y in place of z. y is z's successor z->left->parent = y; y->left = z->left; if (y != z->right) { x_parent = y->parent; if (x) x->parent = y->parent; y->parent->left = x; // y must be a left child y->right = z->right; z->right->parent = y; } else x_parent = y; if (root == z) root = y; else if (z->parent->left == z) z->parent->left = y; else z->parent->right = y; y->parent = z->parent; __STD::swap(y->color, z->color); y = z; // y now points to node to be actually deleted } else { // y == z x_parent = y->parent; if (x) x->parent = y->parent; if (root == z) root = x; else if (z->parent->left == z) z->parent->left = x; else z->parent->right = x; if (leftmost == z) if (z->right == 0) // z->left must be null also leftmost = z->parent; // makes leftmost == header if z == root else leftmost = __rb_tree_node_base::minimum(x); if (rightmost == z) if (z->left == 0) // z->right must be null also rightmost = z->parent; // makes rightmost == header if z == root else // x == z->left rightmost = __rb_tree_node_base::maximum(x); } if (y->color != __rb_tree_red) { while (x != root && (x == 0 || x->color == __rb_tree_black)) if (x == x_parent->left) { __rb_tree_node_base* w = x_parent->right; if (w->color == __rb_tree_red) { w->color = __rb_tree_black; x_parent->color = __rb_tree_red; __rb_tree_rotate_left(x_parent, root); w = x_parent->right; } if ((w->left == 0 || w->left->color == __rb_tree_black) && (w->right == 0 || w->right->color == __rb_tree_black)) { w->color = __rb_tree_red; x = x_parent; x_parent = x_parent->parent; } else { if (w->right == 0 || w->right->color == __rb_tree_black) { if (w->left) w->left->color = __rb_tree_black; w->color = __rb_tree_red; __rb_tree_rotate_right(w, root); w = x_parent->right; } w->color = x_parent->color; x_parent->color = __rb_tree_black; if (w->right) w->right->color = __rb_tree_black; __rb_tree_rotate_left(x_parent, root); break; } } else { // same as above, with right <-> left. __rb_tree_node_base* w = x_parent->left; if (w->color == __rb_tree_red) { w->color = __rb_tree_black; x_parent->color = __rb_tree_red; __rb_tree_rotate_right(x_parent, root); w = x_parent->left; } if ((w->right == 0 || w->right->color == __rb_tree_black) && (w->left == 0 || w->left->color == __rb_tree_black)) { w->color = __rb_tree_red; x = x_parent; x_parent = x_parent->parent; } else { if (w->left == 0 || w->left->color == __rb_tree_black) { if (w->right) w->right->color = __rb_tree_black; w->color = __rb_tree_red; __rb_tree_rotate_left(w, root); w = x_parent->left; } w->color = x_parent->color; x_parent->color = __rb_tree_black; if (w->left) w->left->color = __rb_tree_black; __rb_tree_rotate_right(x_parent, root); break; } } if (x) x->color = __rb_tree_black; } return y; }