rb_tree红黑树
1、概念:
标准库的std::map、std::mulitmap、std::set、 std::multiset统称为关联式容器,其底层数据结构是基于红黑树实现的。
红黑树作为一种二叉树,满足以下规则:
1)每个节点不是红色就是黑色
2)根节点为黑色
3)如果节点为红色,其子节点必须为黑色
4)任何一节点至树尾的任何路径,所含的黑节点树必须相同
如果不满足以上规则,就需要调整颜色并旋转树形
2、红黑树的实现
2.1 红黑树节点
红黑树的节点包含5个属性:自身颜色(红或黑)、指向父节点的指针、指向左子节点的指针、指向右子节点的指针,加上自身存储的数据,
其代码实现如下:
enum rb_tree_color { s_red = false, s_black = true }; // 红黑树节点 template <typename Value> struct Rb_tree_node { typedef rb_tree_color color_type; typedef Rb_tree_node<Value>* link_type; // 一直向左,可找到最小节点 static link_type minimum(link_type x) { while (x->m_left != 0) { x = x->m_left; } return x; } // 一直向右,可找到最大节点 static link_type maximum(link_type x) { while (x->m_right != 0) { x = x->m_right; } return x; } Value m_value_field; //节点值 color_type m_color; // 节点颜色 link_type m_parent; // 父节点 link_type m_left; // 左子节点 link_type m_right; // 右子节点 };
2.2 迭代器实现
迭代器的递增操作分四种情况:
1) 如果有右子节点,如 节点15 递增,需要先右,再一直往左操作,节点20就是所求
2) 如果没有右子节点
a. 例如节点25、节点70递增,先找父节点,只要自身是父节点的右子节点,则一直向上,直到不是右子节点,此时父节点就是所求
b. 例如节点5,节点10递增,父节点就是所求
c. 存在特殊情况,如图2所示,根节点30递增,在a、b逻辑基础上需要加上特殊判断。
迭代器的递减操作分三种情况:
1)如果对header递减,指向其右子节点,即整棵树的max节点
2)如果有左子节点,则先左再一直往右,例如节点75
3)如果没有左子节点,先找父节点,如果自身是父节点的左子节点,则一直向上,直到不是左子节点,即为所求,例如节点20
迭代器的代码实现:
// 红黑树迭代器 template <typename Value> struct Rb_tree_iterator { typedef Value value_type; typedef Value& reference; typedef Value* pointer; typedef Rb_tree_iterator<Value> self; typedef Rb_tree_node<Value>* link_type; Rb_tree_iterator() :m_node(nullptr) {} Rb_tree_iterator(link_type x) { m_node = x; } // 递增操作 void increment() { if (m_node->m_right != 0) { m_node = m_node->m_right; // 1)如果有右子节点,先右后左到底就是 while (m_node->m_left != 0) { m_node = m_node->m_left; } } else { link_type y = m_node->m_parent; // 2) 没有右子节点,先找父节点 while (m_node == y->m_right) { // 一直向上,直到不是右子节点位置 m_node = y; y = y->m_parent; } if (m_node->m_right != y) // 排除特殊情况,根节点无右子节点,对根节点递增 { m_node = y; //包含a、b、c三种情况, } } } // 递减操作 void decrement() { if (m_node->m_color == s_red && // 1)如果node 为 header, 其右子节点为mostright, 指向整棵树的max节点 m_node->m_parent->m_parent == m_node) // 该节点是红节点,且父节点的父节点等于自己,右子节点就是 { m_node = m_node->m_right; } else if (m_node->m_left != 0) // 2) 如果有左子节点,先左后右,右到底就是 { link_type y = m_node->m_left; while (y->m_right != 0) { y = y->m_right; } m_node = y; } else // 3)如果没有左子节点,找父节点,如果是左子节点,一直向上,直到不是 { // 左子节点 link_type y = m_node->m_parent; while (m_node == y->m_left) { m_node = y; y = y->m_parent; } m_node = y; } } // 重载操作符 reference operator*() const { return static_cast<link_type>(m_node)->m_value_field; } pointer operator->() const { return &(operator*()); } 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; } bool operator==(const self& x) const { return m_node == x.m_node; } bool operator!=(const self& x) const { return m_node != x.m_node; } link_type m_node; };
2.3 红黑树自平衡操作
情况1:父节点为黑色,不用操作
情况2:父节点为红
1) 伯父节点为红
2)伯为空或黑
a、父节点是祖父节点的左子节点
a1: 新增节点为父节点的右子节点
a2: 新增节点为父节点的左子节点
b、新增节点为父节点的左子节点
b1: 新增节点为父节点的左子节点
b2: 新增节点为父节点的右子节点
代码实现:
// 全局函数,向左旋转 // param1_in: x 旋转节点 // param2_out: root 根节点 template<typename Value> inline void rb_tree_rotate_left(Rb_tree_node<Value>* x, Rb_tree_node<Value>*& root) {// 一共更改了三对指针的指向 Rb_tree_node<Value>* y = x->m_right; // x绕着其右子节点y旋转 x->m_right = y->m_left; // x的右子节点指向y的左子节点 if (y->m_left != 0) { y->m_left->m_parent = x; // y的左子节点的父节点指向x } y->m_parent = x->m_parent; // y的父节点指向x的父节点 if (x == root) // 如果是根节点,指明y为根节点 { root = y; } else if (x == x->m_parent->m_left) { x->m_parent->m_left = y; // x的父节点原先指向x,现改为指向y } else { x->m_parent->m_right = y; // x的父节点原先指向x,现改为指向y } y->m_left = x; // y的左节点指向x x->m_parent = y; // x的父节点指向y }
// 全局函数,向右旋转 // param1_in: x 旋转节点 // param2_out: root 根节点 template<typename Value> inline void rb_tree_rotate_right(Rb_tree_node<Value>* x, Rb_tree_node<Value>*& root) { // 一共更改了三对指针的指向 Rb_tree_node<Value>* y = x->m_left; // x绕着其左子节点y旋转 x->m_left = y->m_right; // x的左子节点指向y的右子节点 if (y->m_right != 0) { y->m_right->m_parent = x; // y的右子节点的父节点指向x } y->m_parent = x->m_parent; // y的父节点指向x的父节点 if (x == root) { root = y; //如果是根节点,指明y为根节点 } else if (x == x->m_parent->m_right) { x->m_parent->m_right = y; // x的父节点原先指向x,现改为指向y } else { x->m_parent->m_left = y; // x的父节点原先指向x,现改为指向y } y->m_right = x; // y的右节点指向x x->m_parent = y; // x的父节点指向y } // 全局函数,插入新节点后令树形平衡 // param1_in :x 新增节点 // param2_out: root 根节点 template<typename Value> inline void rb_tree_rebalance(Rb_tree_node<Value>* x, Rb_tree_node<Value>*& root) { x->m_color = s_red; // 新增节点要为红节点 while (x != root && x->m_parent->m_color == s_red) //父节点为红 { if (x->m_parent == x->m_parent->m_parent->m_left) // 父节点为祖父节点的左子节点 { Rb_tree_node<Value>* y = x->m_parent->m_parent->m_right; // 令y为伯父节点,即父父节点的右子节点 if (y && y->m_color == s_red) // 伯父节点存在,且为红色节点 { x->m_parent->m_color = s_black; // 改父节点为黑 y->m_color = s_black; // 改伯父节点为黑 x->m_parent->m_parent->m_color = s_red; // 更改祖父节点为红 x = x->m_parent->m_parent; // 向上至祖父节点迭代 } else { // 无伯父节点或伯父节点为黑 if (x == x->m_parent->m_right) // 如果新节点为父节点的右子节点 { x = x->m_parent; rb_tree_rotate_left(x, root); // 对x父节点左旋转 } x->m_parent->m_color = s_black; // 改变颜色 x->m_parent->m_parent->m_color = s_red; rb_tree_rotate_right(x->m_parent->m_parent, root); // 对祖父节点右旋转 } } else { // 父节点为祖父节点的右子节点 Rb_tree_node<Value>* y = x->m_parent->m_parent->m_left;// 令y为伯父节点,即父父节点的左子节点 if (y && y->m_color == s_red) // 伯父节点存在,且为红色节点 { x->m_parent->m_color = s_black; // 改父节点为黑 y->m_color = s_black; // 改伯父节点为黑 x->m_parent->m_parent->m_color = s_red; // 更改祖父节点为红 x = x->m_parent->m_parent; // 向上至祖父节点迭代 } else { // 无伯父节点或伯父节点为黑 if (x == x->m_parent->m_left) // 如果新节点为父节点的左子节点 { x = x->m_parent; rb_tree_rotate_right(x, root); // 对x父节点右旋转 } x->m_parent->m_color = s_black; // 改变颜色 x->m_parent->m_parent->m_color = s_red; rb_tree_rotate_left(x->m_parent->m_parent, root);// 对祖父节点左旋转 } } } root->m_color = s_black; // 根节点永远为黑 } //全局函数,删除节点后令树形平衡 //z-待删除点,root-根节点,leftmost-左极点,rightmost-右极点 template<typename Value> inline Rb_tree_node<Value>* rb_tree_rebalance_for_erase(Rb_tree_node<Value>* z, Rb_tree_node<Value>*& root, Rb_tree_node<Value>*& leftmost, Rb_tree_node<Value>*& rightmost) { Rb_tree_node<Value>* y = z; // 调整后实际被删除点的指针 Rb_tree_node<Value>* x = 0; // y的某个子节点 Rb_tree_node<Value>* x_parent = 0; // x的父节点 if (y->m_left == 0) { x = y->m_right; // 这里x可能为null } else { if (y->m_right == 0) { x = y->m_left; // 这里x肯定不为null } else { // z 有两个非空子节点,设定y为z的后继,x为y的右节点,x可能为空 y = y->m_right; while (y->m_left != 0) { y = y->m_left; } x = y->m_right; } } if (y != z) // 重新设置y的连接以取代z,y是z的后继 { z->m_left->m_parent = y; y->m_left = z->m_left; if (y != z->m_right) { x_parent = y->m_parent; if (x) { x->m_parent = y->m_parent; } y->m_parent->m_left = x; // y一定是其父节点的左孩子 y->m_right = z->m_right; z->m_right->m_parent = y; } else { x_parent = y; } if (root == z) { root = y; } else if (z->m_parent->m_left == z) { z->m_parent->m_left = y; } else { z->m_parent->m_right = y; } y->m_parent = z->m_parent; std::swap(y->m_color, z->m_color); y = z; // y 现在指向实际被删除的节点 } else { // y == z x_parent = y->m_parent; if (x) { x->m_parent = y->m_parent; } if (root == z) { root = x; } else { if (z->m_parent->m_left == z) { z->m_parent->m_left = x; } else { z->m_parent->m_right = x; } } if (leftmost == z) { if (z->m_right == 0) // z->m_left也一定为0 {// 设定leftmost为z的父节点,覆盖了z为root,leftmost指向m_header的情况 leftmost = z->m_parent; } else { leftmost = Rb_tree_node<Value>::minimum(x); } } if (rightmost == z) { if (z->m_left == 0) // z->m_right也一定为0 {// 设定rightmost为z的父节点,覆盖了z为root,rightmost指向m_header的情况 rightmost = z->m_parent; } else { rightmost = Rb_tree_node<Value>::maximum(x); } } } if (y->m_color != s_red) { while (x != root && (x == 0 || x->m_color == s_black)) { if (x == x_parent->m_left) { Rb_tree_node<Value>* w = x_parent->m_right; if (w->m_color == s_red) { w->m_color = s_black; x_parent->m_color = s_red; rb_tree_rotate_left(x_parent, root); w = x_parent->m_right; } if ((w->m_left == 0 || w->m_left->m_color == s_black) && (w->m_right == 0 || w->m_right->m_color == s_black)) { w->m_color = s_red; x = x_parent; x_parent = x_parent->m_parent; } else { if (w->m_right == 0 || w->m_right->m_color == s_black) { if (w->m_left) { w->m_left->m_color = s_black; } w->m_color = s_red; rb_tree_rotate_right(w, root); w = x_parent->m_right; } w->m_color = x_parent->m_color; x_parent->m_color = s_black; if (w->m_right) { w->m_right->m_color = s_black; } rb_tree_rotate_left(x_parent, root); break; } } else { Rb_tree_node<Value>* w = x_parent->m_left; if (w->m_color == s_red) { w->m_color = s_black; x_parent->m_color = s_red; rb_tree_rotate_right(x_parent, root); w = x_parent->m_left; } if ((w->m_right == 0 || w->m_right->m_color == s_black) && (w->m_left == 0 || w->m_left->m_color == s_black)) { w->m_color = s_red; x = x_parent; x_parent = x_parent->m_parent; } else { if (w->m_left == 0 || w->m_left->m_color == s_black) { if (w->m_right) { w->m_right->m_color = s_black; } w->m_color = s_red; rb_tree_rotate_left(w, root); w = x_parent->m_left; } w->m_color = x_parent->m_color; x_parent->m_color = s_black; if (w->m_left) { w->m_left->m_color = s_black; } rb_tree_rotate_right(x_parent, root); break; } } } if (x) { x->m_color = s_black; } } return y; }
3、 rb_tree模板类的代码实现
//rb-tree定义 template <typename Key, typename Value, typename KeyOfValue, typename Compare, typename Alloc = std::allocator<Value>> class Rb_tree { protected: typedef Rb_tree_node<Value> rb_tree_node; public: typedef Key key_type; typedef Value value_type; typedef rb_tree_node* link_type; typedef size_t size_type; std::allocator<rb_tree_node> m_alloc; protected: // 申请节点空间 link_type get_node() { return m_alloc.allocate(1); // 申请内存就简单使用std::allocator,主要是验证红黑树 } // 释放节点空间 void put_node(link_type p) { m_alloc.deallocate(p, 1); // 申请内存就简单使用std::allocator,主要是验证红黑树 } // 创建一个节点 link_type create_node(const value_type& x) { link_type tmp = get_node(); rb_tree_node node; node.m_value_field = x; m_alloc.construct(tmp, node); return tmp; } // 复制一个节点 link_type clone_node(link_type x) { link_type tmp = create_node(x->m_value_field); tmp->m_color = x->m_color; tmp->m_left = 0; tmp->m_right = 0; return tmp; } // 释放节点,先析构后释放内存 void destroy_node(link_type p) { m_alloc.destroy(p); put_node(p); } protected: size_type m_node_count; // 数的节点数量 link_type m_header; // header 节点 Compare m_key_compare;// 节点间的键值大小比较准则 KeyOfValue m_keyOfValue; // 求取极大值和极小值 node class 有实现此功能,交给它们完成即可 static link_type minimum(link_type x) { return (link_type)Rb_tree_node::minimum(x); } static link_type maximum(link_type x) { return (link_type)Rb_tree_node::maximum(x); } public: // 定义迭代器 typedef Rb_tree_iterator<value_type> iterator; private: iterator m_insert(link_type x, link_type y, const value_type& v) { link_type x1 = (link_type)x; link_type y1 = (link_type)y; link_type z1; if (y1 == m_header || x1 != 0 || m_key_compare(KeyOfValue()(v), m_keyOfValue(y1->m_value_field))) { z1 = create_node(v); // 创建一个新节点 y1->m_left = z1; // 这样当y为header时,z1为leftmost() if (y1 == m_header) { m_header->m_parent = z1; m_header->m_right = z1; } else if (y1 == m_header->m_left) { m_header->m_left = z1; // 保证rightmost()指向最左点 } } else { z1 = create_node(v); // 创建新节点 y1->m_right = z1; // 新节点是y的右子节点 if (y1 == m_header->m_right) { m_header->m_right = z1; // 保证rightmost()指向最右点 } } z1->m_parent = y1; // 设定新节点的父节点 z1->m_left = 0; // 设定左子节点 z1->m_right = 0; // 设定右子节点 rb_tree_rebalance(z1, m_header->m_parent); //平衡树调节,参数1为新增节点,参数2 为根节点 ++m_node_count; // 节点数累加 return iterator(z1); // 返回指向新增节点的迭代器 } link_type m_copy(link_type x, link_type p) { link_type top = clone_node(x); top->m_parent = p; if (x->m_right) { top->m_right = m_copy(x->m_right, top); } p = top; x = x->m_left; while (x != 0) { link_type y = clone_node(x); p->m_left = y; y->m_parent = p; if (x->m_right) { y->m_right = copy(x->m_right, y); } p = y; x = x->m_left; } return top; } void initialize() { m_header = get_node(); // 产生一个节点空间,令header指向它 m_header->m_color = s_red; // 令header为红色,用来区分header和root m_header->m_parent = 0; m_header->m_left = m_header; // header 的左子节点为自己 m_header->m_right = m_header; // 令header的右子节点为自己 } // 找到第一个大于或等于k的迭代器 iterator lower_bound(const Key& k) { link_type y = m_header; link_type x = m_header->m_parent; while (x != 0) { if (!m_key_compare(m_keyOfValue(x->m_value_field), k)) { y = x; x = x->m_left; } else { x = x->m_right; } } return iterator(y); } // 找到第一个大于k的迭代器 iterator upper_bound(const Key& k) { link_type y = m_header; link_type x = m_header->m_parent; while (x != 0) { if (m_key_compare(k, m_keyOfValue(x->m_value_field))) { y = x; x = x->m_left; } else { x = x->m_right; } } return iterator(y); } std::pair<iterator,iterator> equal_range(const Key& k) { return std::pair<iterator, iterator>(lower_bound(k), upper_bound(k)); } void m_erase(link_type x) { while (x != 0) { m_erase(x->m_right); link_type y = x->m_left; destroy_node(x); x = y; } } public: // 构造函数 Rb_tree() : m_node_count(0) { initialize(); } Rb_tree(const Rb_tree& x) : m_node_count(0) { if (x._M_root() == 0) { m_header->m_color = s_red; m_header->m_parent = 0; m_header->m_left = m_header; m_header->m_right = m_header; } else { m_header->m_color = s_red; m_header->m_parent = m_copy(x.m_header->m_parent, m_header); m_header->m_left = minimum(m_header->m_parent); m_header->m_right = maximum(m_header->m_parent); } m_node_count = x.m_node_count; } Rb_tree(Rb_tree&& x) { m_header = x.m_header; m_node_count = x.m_node_count; x.m_header = 0; x.m_node_count = 0; } ~Rb_tree() { clear(); put_node(m_header); } Rb_tree& operator=(const Rb_tree& x) { if (this != &x) { clear(); m_node_count = 0; if (x.m_header->m_parent == 0) { m_header->m_parent = 0; m_header->m_left = m_header; m_header->m_right = m_header; } else { m_header->m_parent = m_copy(x.m_header->m_parent, m_header); m_header->m_left = minimum(m_header->m_parent); m_header->m_right = maximum(m_header->m_parent); m_node_count = x.m_node_count; } } return *this; } Rb_tree& operator=(Rb_tree&& x) { this->swap(x); } public: iterator begin() { return m_header->m_left; } iterator end() { return m_header; } bool empty() const { return m_node_count == 0; } size_type size() const { return m_node_count; } void swap(Rb_tree& t) { std::swap(m_header, t.m_header); std::swap(m_node_count, t.m_node_count); } std::pair<iterator, bool> insert_unique(const value_type& v) { { link_type y = m_header; link_type x = m_header->m_parent; // 从根节点开始 bool comp = true; while (x != 0) // 从根节点开始,往下寻找适当的插入点 { y = x; comp = m_key_compare(m_keyOfValue(v), m_keyOfValue(x->m_value_field)); // v键值是否小于节点键值? x = comp ? x->m_left : x->m_right; // 遇到“大”则往左,遇到“小或等于”则往右 } // y即为插入点的父节点 iterator j = iterator(y); // 令迭代器j指向插入点的父节点y if (comp) // 如果离开while循环是comp为真,将插入左侧 { if (j == begin()) // 如果插入点的父节点为最左节点 { return std::pair<iterator, bool>(m_insert(x, y, v), true); // x为插入点,y为插入点的父节点,v为新值 } else { --j; // 减一用于下一步验证,即递减一次就小于新值,不能是等于 } } if (m_key_compare(m_keyOfValue(j.m_node->m_value_field), m_keyOfValue(v))) // 确保此处的j小于v, 小于新值 { return std::pair<iterator, bool>(m_insert(x, y, v), true);// x为插入点,y为插入点的父节点,v为新值 } return std::pair<iterator, bool>(j, false); //此处,新值必与树中键值重复,返回错误 } } iterator insert_equal(const value_type& v) { link_type y = m_header; link_type x = m_header->m_parent; while (x != 0) { y = x; x = m_key_compare(m_keyOfValue(v), m_keyOfValue(x->m_value_field)) ? x->m_left : x->m_right; } return m_insert(x, y, v); } // 删除节点x void erase(iterator x) { link_type y = (link_type)rb_tree_rebalance_for_erase(x.m_node, m_header->m_parent, m_header->m_left, m_header->m_right); destroy_node(y); --m_node_count; } size_type erase(const key_type& x) { std::pair<iterator, iterator> p = equal_range(x); size_type n = 0; iterator first = p.first; while ( first != p.second ) { ++first; ++n; } erase(p.first, p.second); return n; } void erase(iterator first, iterator last) { if (first == begin() && last == end()) { clear(); } else { while (first != last) { erase(first++); } } } void clear() { if (m_node_count != 0) { m_erase(m_header->m_parent); m_header->m_left = m_header; m_header->m_parent = 0; m_header->m_right = m_header; m_node_count = 0; } } iterator find(const key_type& k) { link_type y = m_header; link_type x = m_header->m_parent; while (x != 0) { if (!m_key_compare(m_keyOfValue(x->m_value_field), k)) // 此处x向左移动 { y = x, x = x->m_left; } else { x = x->m_right; // 此处x向右移动 } } iterator j = iterator(y); return (j == end() || m_key_compare(k, m_keyOfValue(j.m_node->m_value_field))) ? end() : j; } size_type count(const key_type& x) const { std::pair<iterator, iterator> p = equal_range(x); size_type n = 0; iterator first = p.first; while (first != p.second) { ++first; ++n; } return n; } };
typename