Data Structure Basics (18)--design and implementation of red and black trees (1)

Source: Internet
Author: User

The red-black tree is a self-balancing two-fork search tree, a data structure used in computer science, typically for associative arrays (Map/set in C + + STL). It was invented in 1972 by Rudolf Bayer, which he called "symmetric binary B-tree", and its modern name was obtained by Leo J. Guibas and Robert Sedgewick in a paper written in 1978. The red-black tree is complex, but its operation has a good worst-case run time and is efficient in practice: it can be searched, inserted and deleted in O (log n) time, where n is the number of elements in the tree (source Baidu Encyclopedia).

Introduction to R-b tree introduced by the algorithm introduction:

Red-black tree, a binary lookup tree, but adds a storage bit to each node that represents the color of the node, which can be red or black. By limiting the way each node is shaded from the root to the leaf, the red-black tree ensures that no path is twice times longer than the other path, and thus is nearly balanced .

Because the red and black tree is also a binary search tree/Two-fork sorting tree, so the red and black tree also satisfies the general nature of the binary search tree (for the general nature of binary search trees, please refer to the blog: http://blog.csdn.net/zjf280441589/article/details/42611161)

However, because the normal two-fork search tree does not have the function of automatic balance, so the ordinary two-fork search tree is likely to degenerate into a linked list, if the binary tree degenerate into a linear chain with n nodes, then the insertion/deletion/Find operation worst case run time becomes O (n).

So there is the red black tree, his final search, insert, delete the time complexity of the worst case is still O (Logn), and the reason why the red black tree so cattle is it in the binary search tree based on the addition of coloring and related properties, this is the red and black rules:


Red and black rules

1. Each node is not red or black;

2. The root is always black;

3. Each leaf node (leaf node refers to a nil pointer or null node at the end of the tree) is black;

4. If the node is red, its child nodes must be black;

5. Each path from the root to the leaf node must contain the same number of black nodes;

If the red-black rule is not met after inserting/deleting nodes in the red-black tree, the following correction method is used:

1. Change the color of the node;

2. Rotation;

Red and Black tree knot.
Template <typename type>class redblacknode{    friend redblacktree<type>;p ublic:private:    Redblacknode (const Type &_element = Type (),                 redblacknode *_left = null,                 redblacknode *_right = null,                 int _color = redblacktree<type>::black)        : Element (_element), left (_left), right (_right), color (_color) {} private://in order to test when the red and black trees have not been completed/so as public, when the red black tree is completed,//is to change it to private; public:    Type            element;   Node value    redblacknode    *left;    Redblacknode    *right;    Red black tree color    int color             ;};

red and black trees
Template <typename Type>class redblacktree{public://Defines the alias for the node typedef redblacknode<type> node; enum {red, black};p ublic://The operation supported by the red and black tree is not yet complete,//and function functions (such as destructors, insert operations)//implementation is not ideal,//But with the evolution of red and Black Tree Code,//These code will    Continuous improvement of Redblacktree (const Type &neginf);    ~redblacktree (); void Insert (const Type &data);p rivate://to test when the red-black tree is not yet complete//so as public, when the red black tree is completed,//is changed to private; public://    Head (pseudo-root node) pointing to the red-black tree//redblacknode<type> *header;    Node *header;    NULL node *nullnode;  The required pointer in the insertion process is Node *current;   Current node *parent;    Parent node *grand;    Grandfather nodes (grandpa) node *great;    Great-grandfather node (Grandpa's father)/* Single rotation *///With Left child rotation: rotate to the right void Rotatewithleftchild (Node *& K2) const;    Rotate with child: Rotate Left void rotatewithrightchild (Node *& K1) const;    /* Double rotation *///Right turn void Doublerotatewithleftchild (Node *& K3) const; Turn left void Doublerotatewithrightchild (Node *& K1) const;};

Construction and destruction

Constructor template <typename type>redblacktree<type>::redblacktree (const Type &neginf) {    Nullnode = New Node ();    Header = new Node (Neginf, Nullnode, Nullnode);} This version of the destructor implementation is not perfect template <typename Type>redblacktree<type>::~redblacktree () {    delete nullnode;    Delete header;}

Insert for a binary lookup tree

At this point the insert is actually an ordinary//two-fork search tree Insert, completely do not take care of the balance of the//two fork tree, and the implementation of the red and Black rules template <typename type>void redblacktree< Type>::insert (const Type &data) {    great = Grand = Parent = current = header;    In this place nullnode becomes data, as Sentinel    nullnode->element = data;    while (current->element! = data)    {        //Let grandfather become a great-grandfather, father became a grandfather, he became a father        //Everyone grew a generation        great = grand;        Grand = parent;        parent = current;        Current = (Data < current->element)? Current->left                  : current->right;    }    If the tree contains the same element if (current!    = Nullnode)        throw duplicateitemexception ();    Current = new Node (data, Nullnode, Nullnode);    if (Data < parent->element)        parent->left = current;    else        parent->right = current;    On subsequent releases, you need to add auto-balance (that is, implement red-black rules), red-black Tree}

Single Rotation

Note: The medial grandson node moves laterally (note node 37);


left ( single ) Spin :

When doing a left-handed operation on a node K1, we assume that its right child K2 is not nil[t] (K1 can be any left child node that is not nil[t]; The chain of left-K1 to K2 is a "branch axis", which makes K2 a new root of the subtree, while the K2 's child B becomes the right child of K1.

Implement//Turn left to template <typename type>void redblacktree<type>::rotatewithrightchild (Node *& K1) const{    Node *k2 = k1->right;    Node B transverse movement    k1->right = k2->left;    Make K2 k1    k2->left = K1;    Make K2 the root (where the K2 replaces the K1)    k1 = K2;}

Right ( single ) rotation :

The process is similar to the left ;

Implement//Right-turn template <typename type>void redblacktree<type>::rotatewithleftchild (Node *& K2) const{    //First move    the B laterally Node *k1 = k2->left;    K2->left = k1->right;    Make k1 k2    k1->right = K2;    Make K1 the root (where the K1 replaces the K2)    k2 = K1;}

Test (after completing a single rotation):

(Constructs a binary look-up tree, the left side is not rotated before, right is rotated)

The test code is as follows: int main () {//uses Neg_inf to represent negative Infinity const int neg_inf =-999999;    Redblacktree<int> tree (Neg_inf);    Single rotation time test data tree.insert (30);    Tree.insert (15);    Tree.insert (70);    Tree.insert (20);    cout << tree.header->right->element << Endl;    cout << tree.header->right->left->element << Endl;    cout << tree.header->right->right->element << Endl;   cout << tree.header->right->left->right->element << Endl;    20//Rotate Right cout << "rotate Right" << Endl;    Tree.rotatewithleftchild (Tree.header->right);    cout << tree.header->right->element << Endl; cout << tree.header->right->right->element << Endl;   cout << tree.header->right->right->left->element << Endl;   cout << tree.header->right->right->right->element << Endl; 70//Then turn left (and turn back again) cout << "toLeft rotation "<< Endl;    Tree.rotatewithrightchild (Tree.header->right);    cout << tree.header->right->element << Endl;    cout << tree.header->right->left->element << Endl;    cout << tree.header->right->right->element << Endl;   cout << tree.header->right->left->right->element << Endl; return 0;}


Data Structure Basics (18)--design and implementation of red and black trees (1)

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.