Analysis of red and black tree algorithm

Source: Internet
Author: User

About red and black trees


Red-black tree is a self-balancing binary search tree, also has the characteristics of a two-fork tree, keeping the right side is always greater than the left node key features. The AVL tree mentioned earlier is also a variant of the binary search tree, which does not reach the height of the AVL tree, in other words, its height is not as high as the AVL tree, but his application is more extensive, and in practice it is quite efficient, and he can find it in O (log n) time, Insert, delete operation . In C + + STL, the variants of red-black trees that are applied toset, Multiset, map, Multimap , and so on.

Red and black tree under the premise of balancing the binary search tree, each node adds a member variable of _color, which is used to mark each node. Next, we'll analyze the insertion algorithm for red and black trees.


An AVL tree needs to meet the following requirements.

1. Every knot, not black or red.

2. The root node of the tree must be black

3, from the root node to the leaf node of any road, no two consecutive red nodes are allowed to exist.

4, for each node, from his beginning to each leaf node of the simple path, the Black node tree is the same.

here is a little more, if the above conditions are met, from the root node, to the leaf node, the longest will not exceed twice times the longest path. (The most extreme cases can be considered)


A brief analysis of ideas


As with the AVL tree, the rotation algorithm must be used to ensure the balance of the tree. Due to the fact that the red and black trees are more (although the code is not very complex), so in the process of rotation here, we do not like the AVL tree, the rotation of the balance factor is adjusted, the red black tree rotation algorithm, simply adjust the current node and its parent, grandparent, Uncle the relative position of the node, after the rotation is complete, we set the node color again.

The insertion algorithm is given below.


First we give a definition of the node.

Enum Color
{
RED,
BLACK
};
Template<typename K, TypeName v>
struct Rbtreenode
{
Rbtreenode<k, v>* _left;
Rbtreenode<k, v>* _right;
Rbtreenode<k, v>* _parent;
K _key;
V _value;
Color _color;
Rbtreenode (const k& key,const v& value)
: _left (NULL)
, _right (NULL)
, _parent (NULL)
, _key (Key)
, _value (value)
, _color (red)//Red node is constructed by default.
{}
};

_key is the key code (_key value is not allowed to repeat), _value is the value, about the node here the constructor, want to say a little more, why the node color to default to red ? Obviously, in general, black nodes are more than red nodes, but here we need to be aware that the adjustments we're targeting are actually mostly red. If the red knot is added under the black knot, it is not necessary to adjust the red node, if more than one black knot is added, it must be adjusted.


Next, you start inserting the nodes.

1. Handling Special Cases

When the tree is empty, the new node is given the root, and then the color can be changed.


if (_root = = NULL) {_root = new Node (key, value); _root->_color = Black;return true;}


2. When the tree is not empty, we first need to find the location where we want to insert the node. Since the red and black tree is a two-fork search tree, the location of the node to be inserted is found by comparing the key value and the current node size of the node to be inserted. At the same time, it opens up space for the node and determines the direction relation of the parent node.

node* cur = _root; node* parent = null;while (cur! = NULL) {if (Key > Cur->_key) {parent = Cur;cur = Cur->_right;} else if (Key < Cur->_key) {parent = Cur;cur = Cur->_left;} Else{return false;}} cur = new Node (key, value), if (Key > (Parent->_key)) {Parent->_right = Cur;cur->_parent = parent;} Else{parent->_left = Cur;cur->_parent = parent;}

When the parent node of the insertion node is a black node, no adjustments need to be made and only the parent node can be contacted.

3, the following is the need for our special treatment of several cases.

We give four node node cur (to insert node), parent (cur's father node), grandparent (cur's grandfather node), uncle (Uncle Cur).

Situation one,

Parent is black, uncle exists and is red

650) this.width=650; "src=" Http://s2.51cto.com/wyfs02/M01/89/9F/wKiom1gYVE2CRjhqAABWzAQAwGw226.png "title=" 1.png " alt= "Wkiom1gyve2crjhqaabwzaqawgw226.png"/>

A triangular node simply represents a possible node, possibly empty.

When Cur is a new insertion node, the A-E nodes are empty nodes, and since there can be no contiguous red nodes, we need to turn the parent node and the Uncle node into black. Careful words can be found, the grandparent junction becomes red, this is because when grandparent is not the root node, we this subtrees tree on one branch of the black node will be one more, so we need to change the grandparent node to red, and then continue to adjust upward. After the insert is complete, we only need to uniformly reassign the root node to red.

Situation Two,

The parent is red, the Uncle node does not exist, or the Uncle node exists, but it is black.

650) this.width=650; "src=" Http://s4.51cto.com/wyfs02/M00/89/9F/wKiom1gYYAjykLoIAAD0M3hG5tM480.png "title=" 3.png " alt= "Wkiom1gyyajykloiaad0m3hg5tm480.png"/>


When you see the first picture, do not suspect there is a problem with the painting, this situation is possible, that is to say, cur is adjusted up, from my previous situation adjusted over, although looking at the grandparent of the left and right side of the road black knot points are not the same, but I also have the following Triangle node.

Now I need to rotate here, why can't we just change the color? Because we have thrown over the triangular junction, with the grandparent node as the boundary, the leftmost branch and the last branch, the black knot point difference one. The diagram of the rotation, as shown, rotates to the right with the grandparent node as the axis. rotates the grandparent node as the right subtree of the parent node. At the same time, it is necessary that the grandparent node is not necessarily the root, we need to reserve and judge the grandparent->_parent nodes in advance and then reassign them to parent->_parent.


Situation three,

If you can understand the second situation, the third case is easy to understand a lot, and the second case, just as the cur is the right subtree of the parent, we need to first take the parent as the axis, rotate to the left, get the above situation, then the grandparent axis to the right. Such as.


650) this.width=650; "src=" Http://s3.51cto.com/wyfs02/M00/89/9F/wKiom1gYXv2gYEMCAADKDeliXQg520.png "title=" 2.png " alt= "Wkiom1gyxv2gyemcaadkdelixqg520.png"/>

Noteworthy point, but also a beginning to write code always verify the error of a problem, we first take the parent axis left, then see, cur at this time become parent->_parent, if at this time according to the situation of the two processing mode, the node color will certainly have problems, so, in, I specifically gave a diagram that exchanges the parent and cur pointers, noting that only the pointer is exchanged.



Here, the basic situation of the red and black trees and processing finished, and then there is when the parent is at the beginning of the grandparent in the right sub-tree of several cases, and the above rotation into a mirror of the relationship. The specific code is given below:


Bool insert (Const k& key,const v& value) {//Empty tree if  (_root == NULL {_root = new node (key, value); _root->_color = black;return true;} Build the node and insert it into the corresponding location node* cur = _root; node* parent = null;while  (cur != null) {if  (key > cur->_key ) {parent = cur;cur = cur->_right;} else if  (Key < cur->_key) {parent = cur;cur = cur->_left;} Else{return false;}} Cur = new node (Key, value);if  (key >  (Parent->_key)) {parent->_ Right = cur;cur->_parent = parent;} Else{parent->_left = cur;cur->_parent = parent;} Start adjusting while  (cur != _root && parent->_color == red) {// If the color of the parent is red,parent, it must not be the root node, and the grandfather node color is BLACKNODE*&NBSP;GRANDPARENTNODE&NBSP;=&NBSP;PARENT-&GT;_PArent;//grandparentnode->_color = black;if  (parent == grandparentnode->_left) { Uncle node* unclenode = grandparentnode->_right;//Node uncleif  (unclenode &&   (unclenode->_color == red))//uncle is not empty and Uncle->color is red{parent->_color =  black;unclenode->_color = black;grandparentnode->_color = red;cur =  Grandparentnode;parent = cur->_parent;} Else//uncle is empty, or Uncle->color is black{if  (cur == parent->_right) {Rotatel (parent); Std::swap ( Parent, cur);} Rotater (Grandparentnode);p Arent->_color = black;grandparentnode->_color = red;break;}} Else//parent == grandparent->_right{node* unclenode = grandparentnode->_left;if   (unclenode &&  (unclenode->_color == red))//uncle exists, and color is  red{ parent->_color = black;unclenode->_color = Black;grandparentnode->_color = red;cur = grandparentnode;parent = cur->_ Parent;} Else//uncle does not exist, or uncle->color is black {if  (cur == parent->_left) {rotater (parent); Std::swap (cur, parent);} Rotatel (grandparentnode); grandparentnode->_color = red;parent->_color = black;break;}} Unify the color of the root node into black _root->_color = black;return true;}


The insertion of the red-and-black tree junction is over here, and what we can find is that we have been focusing on the Uncle node, which is Cur's uncle's point. This is a core of the red and black tree inserted into the mind.

Below, on the basic characteristics of red and black trees, give a test function to determine whether the red and black trees meet the requirements.


Bool isbalance () {if  (_root == null) return true;if  (_root->_color ==  red) return false;int count = 0; node* cur = _root;while  (cur != null) {if  (cur->_color == black ) {count++;} Cur = cur->_left;} Int k = 0;return _isbalance (_root, count, k);} Bool _isbalance (node* root, const int& count, int k) {if  (root  == null) return true;if  (root != _root && root->_color  == red) {if  (root->_parent->_color == red) {cout <<  "Continuous red Knot"  << root->_key << endl;return false;}} if  (Root->_color == black) k++;if  (root->_left == null &&  root->_right == null) {if  (k == count) return true;else{cout < <  "Black node Unequal"  << root->_key << endl;return false;}} Return _isbalance (root->_left, count, k)  && _isbalance (Root->_right,  count, k);}


the application of red and black trees is far more than the AVL tree, or at the beginning we said, in fact, the height of the red and black trees is relatively higher than the AVL tree, but this does not affect too much. Because our time complexity is around O (log n), when n = 1 billion, log (n) is only 30. But on the other hand, because the red and black trees are less demanding than AVL trees, when we insert a node, the relative number of adjustments is much less, this is the advantage of red and black trees.

------Muhuizz Finishing

This article is from the "Twilight Back" blog, make sure to keep this source http://muhuizz.blog.51cto.com/11321490/1868200

Analysis of red and black tree algorithm

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.