Red and black Trees

Source: Internet
Author: User

The red-black tree is a balanced two-fork sort tree, first it is a two-fork sort tree, i.e. its nodes are orderly; Secondly, it is a kind of balance tree, so its search efficiency is relatively excellent

Five properties of red and black trees:

1. Each node is either red or black.

2, the root node must be black

3, the leaf node (that is, the null node) is black

4, if a node is red, then its two children must be black

5, for each node, it all the paths to the leaf node contains the same number of black nodes


Because of the nature of 5, the newly inserted node's color must be red!

Due to the nature of 4, the new insertion node may have damaged the balance of the red and black tree, so it needs to be adjusted

Note that the initial insertion position of each node is at the bottom of the tree, after insertion to determine whether it violates the nature of the red and black trees, if violated, then need to adjust


Realize:

#ifndef rb_rbtree_h#define rb_rbtree_h#include <iostream> #include <string>using namespace std;struct rbtreenode;//The comparison function of the tree node data, if not set then by default the typedef int (*RBTREEDATACOMPAREFUNC) (void* data1,void* data2) is compared by the pointer;// Traversing a tree's handler function typedef void (*rbtreenodehandle) (void* userdata,rbtreenode* node);//red-black tree nodes struct rbtreenode{enum Rbtreenod    EColor {//red,//black,};        Rbtreenode () {data = 0;        left = 0;        right = 0;        parent = 0;    color = red;    }//Data void*;    color int color;    Father Struct rbtreenode* parent;    Left child struct rbtreenode*;    Right child struct rbtreenode*;        Gets the minimum node of the subtree with node root static rbtreenode* Mini (rbtreenode* node) {if (node = = 0) return 0;        while (Node->left! = 0) Node =node->left;    return node;           }//Get the maximum node with node as the subtree static rbtreenode* max (rbtreenode* node) {if (node = = 0) return 0;        while (node->right! = 0) node = node->right;    return node;    }};typedef rbtreenode* prbtreenode;//Red and Black Tree Class Rbtree{public:rbtree ();    Rbtree (Rbtreedatacomparefunc comparefunc);    ~rbtree ();    rbtreenode* Root ();    size_t Size ();    BOOL Empty ();    void Clear ();    Insert node rbtreenode* Insert (void* data);    Get the leftmost node rbtreenode* leftmost ();    Get the rightmost node rbtreenode* rightmost ();    Readjust balance void ReBalance (rbtreenode* x);    Rotate the void Rotateleft (rbtreenode* x) to the left;    Rotates the void Rotateright (rbtreenode* x) to the right;    Delete the node with value equal to data void remove (void* data);    Delete node, along with its child node void remove (rbtreenode* node);    Delete the left node of the node (along with its child nodes) void Removeleft (rbtreenode* node);    Delete the right node (along with its child nodes) of the nodes node, void Removeright (rbtreenode* node);    The middle sequence recursively iterates through void Midordertraverse (Rbtreenodehandle handle,void* userdata,rbtreenode* node = 0); Pre-order recursive traversal of void Preordertraverse (Rbtreenodehandle handle,void* USERDATA,RBTreenode* node = 0);    Subsequent recursive traversal of void Postordertraverse (Rbtreenodehandle handle,void* userdata,rbtreenode* node = 0);    Find rbtreenode* Find (void* data);    rbtreenode* Find (void* data,prbtreenode& parentnode);    size_t Depth (rbtreenode* node = 0);    size_t Leafs (rbtreenode* node = 0);p rivate:void Clearrecu (rbtreenode* node);    rbtreenode* Findrecu (rbtreenode* node,void* data,prbtreenode& parentnode);    Middle order recursive traversal of void Midordertraverserecu (Rbtreenodehandle handle,void* userdata,rbtreenode* node);    Pre-order recursive traversal of void Preordertraverserecu (Rbtreenodehandle handle,void* userdata,rbtreenode* node);    Subsequent recursive traversal of void Postordertraverserecu (Rbtreenodehandle handle,void* userdata,rbtreenode* node);    size_t Depthrecu (rbtreenode* node); size_t Leafsrecu (rbtreenode* node);p rivate://M_phead's father always points to the root node//M_phead left pointing to the leftmost node (i.e. the node with the lowest value)//M_phead RI    Ght points to the right-most node (that is, the node with the largest value) rbtreenode* M_phead;    The number of nodes in the red-black tree size_t m_nsize; Comparison function RbtreedAtacomparefunc M_comparefunc;}; #endif//Rbtree_h

#include "rbtree.h"//Default node value comparison function int Defaultrbtreenodecomparefunc (void* data1,void* data2) {if (data1 = data2) re    Turn 0;    if (Data1 < data2) return-1; return 1;}    Constructor Rbtree::rbtree () {m_phead = new Rbtreenode;    M_phead->color = rbtreenode::red;    M_phead->left = M_phead;    M_phead->right = M_phead;    m_phead->parent = 0;    m_nsize = 0; M_comparefunc = Defaultrbtreenodecomparefunc;}    Rbtree::rbtree (Rbtreedatacomparefunc comparefunc) {m_nsize = 0;    M_phead = new Rbtreenode;    M_phead->color = rbtreenode::red;    M_phead->left = M_phead;    M_phead->right = M_phead;    m_phead->parent = 0; M_comparefunc = Comparefunc;}    Rbtree::~rbtree () {Clear (); Delete M_phead;} Returns the root node rbtreenode* rbtree::root () {return m_phead->parent;} Returns the leftmost node of the red-black tree, which is the node with the minimum value rbtreenode* rbtree::leftmost () {return m_phead->left;} The node that returns the optimal edge of the red-black tree, that is, the node with the maximum value rbtreenode* rbtree::rightmost () {return m_phead->right;} Returns the number of nodes in a red-black tree size_t RBTree::size () {return m_nsize;}    BOOL Rbtree::empty () {if (0 = = m_nsize) return true; return false;}    Clear red black tree void Rbtree::clear () {CLEARRECU (m_phead->parent);    M_phead->color = rbtreenode::red;    M_phead->left = M_phead;    M_phead->right = M_phead;    m_phead->parent = 0; m_nsize = 0;}    Recursive cleanup void Rbtree::clearrecu (Rbtreenode *node) {if (node = = 0) return;    CLEARRECU (Node->left);    CLEARRECU (Node->right);    Delete node; --m_nsize;} Node nodes value is greater than or equal to the left child's value//Insert node rbtreenode* rbtree::insert (void* data) {//Create a new node rbtreenode* insertnode = new Rbtreeno    De    Insertnode->data = data;    The color of the new insertion node is red Insertnode->color = rbtreenode::red;    ++m_nsize; If the root node is empty, then set the current node to the root node//adjust the color to black, because the root of the red and black tree is black if (m_phead->parent = = 0) {m_phead->parent = Insertn        Ode        M_phead->parent->color = Rbtreenode::black;        M_phead->left = Insertnode;    M_phead->right = Insertnode; } ElSE {rbtreenode* node = m_phead->parent;        rbtreenode* currentpnode = node;            Locate the location where the new node should be inserted while (node! = 0) {currentpnode = node;            int compareret = M_comparefunc (Node->data,data);            if (Compareret < 0) {node = node->right;            } else//Compareret >= 0 {node = node->left; }}//Insert the new node into the red-black Tree if (M_comparefunc (Currentpnode->data,data) < 0) {Currentpno            De->right = Insertnode;            Insertnode->parent = Currentpnode;        if (rightmost () = = Currentpnode) M_phead->right = Insertnode;            } else {currentpnode->left = Insertnode;            Insertnode->parent = Currentpnode;        if (leftmost () = = Currentpnode) M_phead->left = Insertnode; }}//insert OK//Next need to adjust ReBalance (Insertnode);} Red black Tree Features://(1) The root node is black//(2) The parent-child node can not be red at the same time (that is, if the Father node is red, then the child node must be black)//(3) any node to null (that is, the tree end) Any path contains the same number of black nodes X's father node is P,x's grandfather is G,x's great-grandfather is Gg,x's uncle or uncle (ie P's brother) is s//there are four cases://1, if the color of P is black, can be directly returned after insertion//2, if the color of P is red, then proceed as follows//2.1, S is black:// 2.1.1, LL: If X is outside the insert, direct LL rotation (P and g), change the color P and g (p to black, g to red)//2.1.2, LR: If x is inserted inside, the LR rotates, the p, X is rotated, and then the G and X are changed to the color (g to red, X to Black)//And then the G is rotated//2.2, S is red://2.2.1, LL: If X is outside the insert, direct will rotate (to P and g), change the color of x (to black), if GG is black, then finish//otherwise need to continue upward ///* * Preprocessing Process: * From a node up, if you encounter a node x of the two child nodes of the color is red * Then the X two child nodes of the color to black, the color of x is changed to red, and then continue upward * If the transformation, X's father and X are red (then X's grandfather will be black, Because the father of X is red), * If the brother of X is red at this point, then you can continue upward processing (because the two sub-nodes that meet p are all red) * If the brother of X is black (then it does not meet the condition of continuing upward), rotation is required * Then the father of X rotates, Only one ll (RR) or LR (or RL) rotation is required here, without having to traverse up and then rotate * Single rotation to change the color of P and G * The first rotation of the double rotation needs to change the color of x and G, the second rotation does not need to change the color */void rbtree::    ReBalance (Rbtreenode *x) {//Insert node starting color is red X->color = rbtreenode::red; If the color of P is black, corresponding to case 1, will not go into the loop//always walk up from X until it reaches the root node while (x! = m_phead->parent && X->p Arent->color = = rbtreenode::red) {//P color is red!!!  If P is the left child of g if (x->parent = = X->parent->parent->left) {//Get S rbtreenode*            Uncle = x->parent->parent->right;                The color of S is red if (uncle && uncle->color = = rbtreenode::red) {//This is the preprocessing process                The color of P is set to black x->parent->color = Rbtreenode::black;                The color of S is set to black uncle->color = Rbtreenode::black;                The color of G is set to red X->parent->parent->color = rbtreenode::red;            Then move the x up to G and continue up the traversal, which is a bottom-up preprocessing process x = x->parent->parent; } else//s color is black {//If x is the right child of P and P is the left child of G, then LR rotation//LR selection will be performed                    That is, the left rotation, then the right rotation if (x = = x->parent->right) {x = x->parent; Rotateleft (x);  }//If x is the left child of P and P is the left child of G, then it will be rotated (direct right rotation)//p to black X->parent->color                = Rbtreenode::black;                The color of g turns red X->parent->parent->color = rbtreenode::red;            Rotating Rotateright (x->parent->parent);            }} else/If p is the right child of G {rbtreenode* uncle = x->parent->parent->left; The color of S is red if (uncle && uncle->color = = rbtreenode::red) {//This is preprocessed                The color of the process//p is set to black x->parent->color = Rbtreenode::black;                The color of S is set to black uncle->color = Rbtreenode::black;                The color of G is set to red X->parent->parent->color = rbtreenode::red;            Move X to G, go up in turn, this is a sub-process of preprocessing x = x->parent->parent;        } else//s color is black    {//If x is the left child of P and P is the right child of G, then the RL rotation (first right rotation, then left rotation) if (x = = X->parent->left) is required.                    {x =x->parent;                Rotateright (x); }//If x is the right child of P, then direct RR rotation (i.e. left rotation)//P color to black X->parent->color = RBTR                Eenode::black;                G color changed to red X->parent->parent->color = rbtreenode::red;            Rotary rotateleft (x->parent->parent); }}} M_phead->parent->color = Rbtreenode::black;} Left rotation (counterclockwise rotation in the middle of X)//After rotation, the right child of X replaces the position of X, while X becomes right's left child//So the left child should be X's child void Rbtree::rotateleft (    Rbtreenode *x) {//Get X's left child rbtreenode* right = x->right;    The right child of X should have left child x->right =right->left;    if (right->left! = 0) {//Right of the left child's father is x right->left->parent = x;    }//Right's father is X's original father right->parent = x->parent; if (x = = M_phead->parent) {m_phead->parent = right;    } else if (x = = x->parent->left) {x->parent->left = right;    } else {x->parent->right = right;    }//X into Right's left child right->left = x; X->parent = right;} Right rotation (centered in x, clockwise rotation)//rotation after X's left child to replace X's position, X becomes left right child//Ieft The original right child to x child void Rbtree::rotateright (Rbtreenode *x    ) {rbtreenode* left = x->left;    X->left =left->right;    if (left->right! = 0) {left->right->parent = x;    } left->parent = x->parent;    if (x = = m_phead->parent) {m_phead->parent = left;    } else if (x = = x->parent->right) {x->parent->right = left;    } else {x->parent->left = left;    } left->right = x; X->parent = left;}    rbtreenode* rbtree::find (void *data) {prbtreenode node = 0; Return Findrecu (M_phead->parent,data,node);} rbtreenode* rbtree::find (void *data, Prbtreenode &parEntnode) {parentnode = 0; Return Findrecu (M_phead->parent,data,parentnode);} rbtreenode* Rbtree::findrecu (Rbtreenode *node, void *data,prbtreenode& parentnode) {if (node = = 0) {Paren        tnode = 0;    return 0;    } if (M_comparefunc (node->data,data) = = 0) return node;    parentnode = node;    rbtreenode* temp = FINDRECU (Node->left,data,parentnode);    if (0! = temp) return temp;    parentnode = node; Return Findrecu (Node->right,data,parentnode);} void Rbtree::P reordertraverse (rbtreenodehandle handle, void *userdata, Rbtreenode *node) {if (node = = 0) return P    REORDERTRAVERSERECU (handle,userdata,m_phead->parent); Return Preordertraverserecu (Handle,userdata,node);} void Rbtree::midordertraverse (Rbtreenodehandle handle, void *userdata, Rbtreenode *node) {if (node = = 0) return M    IDORDERTRAVERSERECU (handle,userdata,m_phead->parent); Return Midordertraverserecu (Handle,userdata,node);} void Rbtree::P ostordertraverse (RBtreenodehandle handle, void *userdata, Rbtreenode *node) {if (node = = 0) return Postordertraverserecu (handle,use    Rdata,m_phead->parent); Return Postordertraverserecu (Handle,userdata,node);} void Rbtree::P reordertraverserecu (rbtreenodehandle handle, void *userdata, Rbtreenode *node) {if (node = = 0) retu    RN;    Handle (Userdata,node);    PREORDERTRAVERSERECU (Handle,userdata,node->left); PREORDERTRAVERSERECU (handle,userdata,node->right);} void Rbtree::midordertraverserecu (Rbtreenodehandle handle, void *userdata, Rbtreenode *node) {if (node = = 0) retu    RN;    MIDORDERTRAVERSERECU (Handle,userdata,node->left);    Handle (Userdata,node); MIDORDERTRAVERSERECU (handle,userdata,node->right);} void Rbtree::P ostordertraverserecu (rbtreenodehandle handle, void *userdata, Rbtreenode *node) {if (node = = 0) ret    urn;    POSTORDERTRAVERSERECU (Handle,userdata,node->left);    POSTORDERTRAVERSERECU (Handle,userdata,node->right); Handle (Userdata,noDE);}    size_t rbtree::D epth (Rbtreenode *node) {if (node = = 0) return Depthrecu (m_phead->parent); else return DEPTHRECU (node);}    size_t rbtree::D epthrecu (Rbtreenode *node) {if (node = = 0) return 0;    if (Node->left = = 0 && Node->right = = 0) return 1;    int leftdepth = DEPTHRECU (node->left);    int rightdepth = DEPTHRECU (node->right);    if (Leftdepth > Rightdepth) return leftdepth + 1; else return rightdepth + 1;}    size_t Rbtree::leafs (Rbtreenode *node) {if (node = = 0) return Leafsrecu (m_phead->parent); else return LEAFSRECU (node);}    size_t Rbtree::leafsrecu (Rbtreenode *node) {if (node = = 0) return 0;    if (Node->left = = 0 && Node->right = = 0) return 1; else return Leafsrecu (node->left) + LEAFSRECU (node->right);}


Red and black Trees

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.