Data Structure BASICS (18) and data structure basics 18

Source: Internet
Author: User

Data Structure BASICS (18) and data structure basics 18

The red/black tree is a self-balancing binary search tree and a data structure used in computer science, A typical purpose is to associate arrays (map/set in C ++ STL ). It was invented by Rudolf Bayer in 1972. It is called the symmetric Binary Tree B. Its modern name is Leo J. guibas and Robert Sedgewick obtained in a paper written in 1978. Although the red/black tree is complex, its operations have a good run time and are efficient in practice: It can be searched in O (log n) time, insert and delete. n is the number of elements in the tree (Source: Baidu encyclopedia ).

 

Introduction to algorithms on R-B Tree:

The Red/Black tree is a binary search tree, but a storage bit is added to each node to indicate the color of the node, which can be Red or Black. By limiting the coloring method of each node on any path from the root to the leaf, the red/black tree ensures that no path is twice longer than other paths, so it is close to balance.

 

Because the red and black trees are also a binary search tree/binary sorting tree, so the red and black trees also meet the general nature of the Binary Search Tree (about the general nature of Binary Search Tree please refer to blog: http://blog.csdn.net/zjf280441589/article/details/42611161)

However, because the common Binary Search Tree does not have the automatic balancing function, the common Binary Search Tree is likely to become a linked list, if a binary tree degrades to a linear chain with n nodes, the run time of the insert/delete/search operation is changed to O (n) in the worst case ).

Therefore, with the red/black tree, the time complexity of his final search, insertion, and deletion is still O (logn) in the worst case ), the reason why the red-black tree is so cool is that it adds coloring and related properties on the basis of the Binary Search Tree. This is the red-black rule:


Rules

1. Each node is either red or black;

2. The root is always black;

3. Each leaf node (leaf node refers to the NIL pointer or NULL node at the end of the tree) is black;

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

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

 

If the red/Black rule is not satisfied after the node is inserted/deleted in the red/black tree, use the following correction method:

1. Change the color of the node;

2. Rotate;

 

Red/black tree node
Template <typename Type> class RedBlackNode {friend RedBlackTree <Type>; public: 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: // to test the function when the red/black tree is not complete, use it as public. When the red/black tree is complete, // when you change it to private; public: Type element; // node value RedBlackNode * left; RedBlackNode * right; // the color of the red/black tree int color ;};

Red/black tree
Template <typename Type> class RedBlackTree {public: // defines the Node alias typedef RedBlackNode <Type> Node; enum {RED, BLACK}; public: // at this time, the operations supported by the red/black tree are not complete, // and the functions (such as destructor and insert operations) // are not ideal, // but with the evolution of the red/black tree code, the code will continuously improve the RedBlackTree (const Type & negInf );~ RedBlackTree (); void insert (const Type & data); private: // to test the function when the red/black tree is not complete, use the function as public, when the red/black tree is complete, // is the time to change it to private; public: // points to the head of the red/black tree (pseudo root node) // RedBlackNode <Type> * header; node * header; // empty Node * nullNode; // the pointer Node * current required during the insertion process; // the current Node * parent; // parent Node * grand; // grandfather Node (Grandpa) Node * great; // grandfather Node (grandpa's father) /* single rotation * // rotate with the left child: rotate with the right void rotateWithLeftChild (Node * & k2) const; // rotate with the child: rotate void rotateWithRightChild (Node * & k1) const to the left;/* Double rotate * // turn right void doubleRotateWithLeftChild (Node * & k3) const; // turn left void doubleRotateWithRightChild (Node * & k1) const ;};

Structure and Structure

// Constructor template <typename Type> RedBlackTree <Type>: RedBlackTree (const Type & negInf) {nullNode = new Node (); header = new Node (negInf, nullNode, nullNode);} // The Destructor implementation of this version is not perfect. template <typename Type> RedBlackTree <Type> ::~ RedBlackTree () {delete nullNode; delete header ;}

Insert of a binary search tree

// At this time, the insert is actually a common // Binary Search Tree insert, and there is no need to take care of the balance of the // binary tree, and the implementation template <typename Type> void RedBlackTree <Type>: insert (const Type & data) {great = grand = parent = current = header; // make nullNode data here as the Sentinel nullNode-> element = data; while (current-> element! = Data) {// Let my grandfather become a great grandfather, my father become a grandfather, and I become a father. // everyone has a generation of great = grand; grand = parent; parent = current; current = (data <current-> element )? Current-> left: current-> right;} // if the fruit 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; // in subsequent versions, you need to add an automatic balance (that is, to implement the red-black rule)-> Red-black tree}

Single Rotation

Note: The inside side of the sun tzu node moves horizontally (note node 37 );


 

Left (single) rotation:

 

When performing a left-hand 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 left-hand side uses the chain between k1 and k2 as the "axis", which makes k2 the New Root of the subtree, while k2's left child B becomes the right child of k1.

// Implement // left-turn template <typename Type> void RedBlackTree <Type >:: rotateWithRightChild (Node * & k1) const {Node * k2 = k1-> right; // Node B moves k1-> right = k2-> left horizontally; // causes k2 to claim k1 k2-> left = k1; // set k2 as the root (so that k2 replaces k1) k1 = k2 ;}

Right (single) rotation:

 

 

The process is similar to that of left-hand;

// Implement // right-turn template <typename Type> void RedBlackTree <Type >:: rotateWithLeftChild (Node * & k2) const {// first move B horizontally Node * k1 = k2-> left; k2-> left = k1-> right; // obtain k2 k1-> right = k2 for k1; // use k1 as the root (replace k1 with k2) k2 = k1 ;}

Test (after the single rotation is completed ):

 

(Construct a binary search tree. The left side is before rotation, and the right side is after rotation)

// Test code: int main () {// use NEG_INF to represent negative infinity const int NEG_INF =-999999; RedBlackTree <int> tree (NEG_INF ); // test data tree for single rotation. 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-> element <endl; cout <tree. header-> right-> left-> right-> element <endl; // 20 // rotate cout to the right <"rotate right" <endl; tree. rotateWithLeftChild (tree. header-> right); cout <tree. header-> right-> element <endl; // 15 cout <tree. header-> right-> element <endl; // 30 cout <tree. header-> right-> left-> element <endl; // 20 cout <tree. header-> right-> element <endl; // 70 // then turn left (and then turn back) cout <"rotate left" <endl; tree. rotateWithRightChild (tree. header-> right); cout <tree. header-> right-> element <endl; cout <tree. header-> right-> left-> element <endl; cout <tree. header-> right-> element <endl; cout <tree. header-> right-> left-> right-> element <endl; // 20 return 0 ;}


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.