Data Structure Retrieval (1), Data Structure Retrieval

Source: Internet
Author: User

Data Structure Retrieval (1), Data Structure Retrieval

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" and Its Modern name is in 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 tree is also a binary search tree, so the red and black tree also meet the general nature of the Binary Search Tree (about the general nature of the Binary Search Tree, please refer to the 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. If the node is red, its child node must be black;

4. Each path from the root node to the leaf node must contain the same number of black nodes (the same black height );

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


According to rule 4, the new node must be red;

According to rule 3, the parent node of the newly added node must be black.

When a new node arrives at the insertion point according to the binary tree rule, but fails to comply with the above rules, you must adjust the color and rotate the tree;

 

Red and black nodes

Template <typename Type> class RedBlackNode {friend RedBlackTree <Type>; 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 complete. In future versions, we will continue to improve the Destructor 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}

Double Rotation

A single rotation problem sometimes occurs (as shown in ):


(If the child node [k1] on the inner side is too deep, moving it one way will not solve the problem)

 

So there is a double rotation.

Double rotation to the right:

1. First, take k1 as the axis, and k1 and k2 rotate to the left;

2. Take k3 as the axis, and k3 and k1 after rotation rotate to the right;

/// Implement // double rotate template to the right <typename Type> void RedBlackTree <Type>: doubleRotateWithLeftChild (Node * & k3) const {// first place its left son (k1) rotate rotateWithRightChild (k3-> left) to the left, and then rotate rotateWithLeftChild (k3) to the right );}

Rotate to the left:

1. First, use k3 as the axis, and k2 and k3 rotate to the right;

2. Take k1 as the axis, and k1 and k2 after rotation rotate to the left;

/// Implement // rotate the template <typename Type> void RedBlackTree <Type>: doubleRotateWithRightChild (Node * & k1) const {// first set its right son (k2) rotate rotateWithLeftChild (k1-> right) to the right, and then rotate rotateWithRightChild (k1) to the left.} // note: in fact, the red and black trees do not use double rotation, but implement a rotate operation by themselves. // here, we only want to learn the theory of double rotation;


Test (after dual rotation ):


(Construct a binary search tree. The left side is before rotation, the right side is after rotation, and the 8 side is used as the axis for double rotation)


Int main () {// use NEG_INF to represent negative infinity const int NEG_INF =-999999; RedBlackTree <int> tree (NEG_INF); // test data tree during double spin. insert (12); tree. insert (16); tree. insert (8); tree. insert (10); tree. insert (4); tree. insert (14); tree. insert (2); tree. insert (6); tree. insert (5); cout <tree. header-> right-> element <endl; // 12 cout <tree. header-> right-> left-> element <endl; // 8 cout <tree. header-> right-> element <endl; // 16 cout <tree. header-> right-> left-> element <endl; // 4 cout <tree. header-> right-> left-> right-> element <endl; // 10 cout <tree. header-> right-> left-> element <endl; // 14 // cout <tree. header-> right-> left-> element <endl; // 5 has been used as a sentinel // cout <tree. header-> right-> left-> right-> element <endl; // 5 cout <tree. header-> right-> left-> element <endl; // 2 cout <tree. header-> right-> left-> right-> element <endl; // 6 cout <tree. header-> right-> left-> element <endl; // 5 cout <"\ n "<endl; // rotate the tree to the right based on 8. doubleRotateWithLeftChild (tree. header-> right-> left); cout <tree. header-> right-> element <endl; // 12 cout <tree. header-> right-> left-> element <endl; // 6 cout <tree. header-> right-> element <endl; // 16 cout <tree. header-> right-> left-> element <endl; // 4 cout <tree. header-> right-> left-> right-> element <endl; // 8 cout <tree. header-> right-> left-> element <endl; // 14 cout <tree. header-> right-> left-> element <endl; // 2 cout <tree. header-> right-> left-> right-> element <endl; // 5 cout <tree. header-> right-> left-> right-> element <endl; // 10}

Exceptions used to implement the red/black tree
class DSException{public:    DSException(const string &_message = string())        : message(_message) {}    ~DSException() {}    virtual string what() const    {        return message;    }    virtual string toString() const    {        return "Exception: " + what();    }private:    std::string message;};class DuplicateItemException : public DSException{public:    DuplicateItemException(const string &_msg = string())        : DSException(_msg) {}};


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.