Overview and template Implementation of Binary Search Tree and red/black tree (2)-red/black tree

Source: Internet
Author: User

In fact, many people will realize that if the binary search tree is used, the final search result will become linear in the case of poor data. For example, if data 1 2 3 4 5 6 7 and the root is 1, other data is inserted on the right side, and finally becomes a linear structure, the performance will deteriorate. How to Improve the binary search tree so that the tree height is close to the logn, this special binary search tree can be implemented using the red and black trees.

Five conditions for red/black trees

1. Each node is either red or black.

2. The root is black.

3. Each leaf node (NiL) is black.

4. If a node is red, both of its sons are black.

5. For each node, all paths from the node to its child nodes contain the same number of black nodes.

4 5 properties ensure that this special Binary Search Tree is almost balanced locally. The introduction to algorithms shows that a red/black tree with N inpoints, the height is at most 2lg (n + 1), and the figure is an example of a Rb tree.

Tree nodes are defined:

typedef enum{RED,BLACK} Color;template<typename T>class RBTreeNode{public:RBTreeNode(){pLeft = pRight = pParent = NULL;}RBTreeNode(T _data):data(_data){pLeft = pRight = pParent = NULL;}public:T data;RBTreeNode<T> *pLeft;RBTreeNode<T> *pRight;RBTreeNode<T> *pParent;Color color;};

Except for one more data color, other definitions are the same as those of the Binary Search Tree.

Operation:

Because the red and black trees need to meet these five properties, dynamic local tree modification is required in the process of constructing and inserting nodes, and deleting nodes, so that the nature can continue to be satisfied.

During the Insert Process, left-and right-hand operations are often used to change the tree structure and maintain the nature of the Binary Search Tree.

A graph is used to describe the left and right sides. In this graph, the left and right sides are opposite processes.

In fact, we need to process three pair pointer fields.

For example, the rotation is pnode and Its right child

Modify the connection relationship of pnode-> parent, the parent-child relationship of pnode, and the left child of the right child of pnode (14 is the Child tree with the root)

The Code is as follows:

//left rotate//template<typename T>void RBTree<T>::left_rotate(RBTreeNode<T> *_pNode){RBTreeNode<T> *pRightSon = _pNode->pRight;if(pRightSon == &nil){return ;}//process the parent of _pNodeif(_pNode->pParent != &nil){if(_pNode->pParent->pLeft == _pNode){_pNode->pParent->pLeft = pRightSon;pRightSon->pParent = _pNode->pParent;}else if(_pNode->pParent->pRight == _pNode){_pNode->pParent->pRight = pRightSon;pRightSon->pParent = _pNode->pParent;}}//in this situation, parent of _pNode is the rootelse{m_pRoot = pRightSon;pRightSon->pParent = &nil;}RBTreeNode<T> *pTmp = _pNode->pLeft;pRightSon->pLeft = _pNode;_pNode->pParent = pRightSon;_pNode->pRight = pTmp;pTmp->pParent = _pNode;}

It is not difficult to write the right-hand code.

When inserting a new node, you can find a suitable position to insert it like the common Binary Search Tree. Make the new node red. The Code is as follows:

//insert a new node into the rb treetemplate<typename T>void RBTree<T>::insert(T data){//create a new nodeRBTreeNode<T>* newNode = new RBTreeNode<T>(data);newNode->color = RED;newNode->pParent = newNode->pRight = newNode->pLeft = &nil;//if current tree is emptyif(m_pRoot == NULL){m_pRoot = newNode;m_pRoot -> color = BLACK;m_pRoot->pParent = &nil;return ;}//pNode for iterating//pInsert for insertionsRBTreeNode<T> *pNode = m_pRoot;RBTreeNode<T> *pInsert = &nil;while(pNode != &nil){if(data > pNode->data){pInsert = pNode;pNode = pNode->pRight;}else if(data < pNode->data){pInsert = pNode;pNode = pNode->pLeft;}else{return ;}}if(pInsert != &nil){if(data > pInsert->data){pInsert->pRight = newNode;}else{pInsert->pLeft = newNode;}newNode->pParent = pInsert;insert_fix_up(newNode);}}

But in this way, the nature of the red and black trees may be damaged. If the tree has only one node, the property 2 is destroyed. For example, if there are multiple nodes in the fruit tree and the father of the newly inserted newnode is a red node, the property 4 is damaged at this time. In reality, we mainly focus on the destruction of nature 4, because the destruction of nature 2 is easily corrected, just set the root to black, because such an operation will not damage any original nature.

If newnode is red and the father is black. Obviously, the nature will not be damaged.

As long as the father is red, the nature is wrong. So we can analyze how to handle this problem.

First, let's look at newnode's uncle node. If it's red, we only need to change the color of newnode's father and uncle to black at the same time, and set grandpa to red at the same time, all properties can be maintained.

However, if the uncle is black, you cannot simply set it as this way, thinking that changing the color will damage the nature.

Therefore, the correct operation is to rotate first.

The Code is as follows:

template <typename T>void RBTree<T>::insert_fix_up(RBTreeNode<T> *_pNode){RBTreeNode<T>* y;while(_pNode->pParent->color == RED){if(_pNode->pParent == _pNode->pParent->pParent->pLeft){y = _pNode->pParent;if(y->pParent->pRight->color == RED){_pNode->pParent->pParent->pRight->color = BLACK;_pNode->pParent->color = BLACK;_pNode->pParent->pParent->color = RED;_pNode = _pNode->pParent->pParent;}else{if(_pNode->pParent->pRight == _pNode){left_rotate(_pNode->pParent);y = _pNode;_pNode = _pNode->pParent;}y->color = BLACK;y->pParent->color = RED;right_rotate(y->pParent);_pNode = y;}}else if(_pNode->pParent == _pNode->pParent->pParent->pRight){y = _pNode->pParent->pParent->pLeft;if(y ->color == RED){_pNode->pParent->color = BLACK;_pNode->pParent->pParent->color = RED;y->color = BLACK;_pNode = _pNode->pParent->pParent;}else{y = _pNode->pParent;if(_pNode->pParent->pLeft == _pNode){y = _pNode;_pNode = _pNode->pParent;right_rotate(_pNode);}y->color = BLACK;y->pParent->color = RED;left_rotate(y->pParent);_pNode = y;}}}m_pRoot->color = BLACK;}

Complete template code:

#include <iostream>#include <stack>namespace DataStructure{typedef enum{RED,BLACK} Color;template<typename T>class RBTreeNode{public:RBTreeNode(){pLeft = pRight = pParent = NULL;}RBTreeNode(T _data):data(_data){pLeft = pRight = pParent = NULL;}public:T data;RBTreeNode<T> *pLeft;RBTreeNode<T> *pRight;RBTreeNode<T> *pParent;Color color;};/***To be a r&b tree, several characteristics must be satisfied:* 1. for each node, it must be black or red* 2. root must be black* 3. leaf node must be black* 4. if one node is red, then two sons must be black* 5. for each node, from which to each leaf, you will get the same number of black nodes, */template<typename T>class RBTree{public:typedef T dateType;typedef RBTreeNode<T> nodeType;public:RBTree(){m_pRoot = NULL;nil.pParent = nil.pRight = nil.pLeft = NULL;nil.color = BLACK;}//insert a new node into the rb treevoid insert(T data);//remove a node from the rb treevoid remove(RBTreeNode<T> *_removeNode);//left rotatevoid left_rotate(RBTreeNode<T> *_pNode);//right rotatevoid right_rotate(RBTreeNode<T>* _pNode);//find the tree nodeRBTreeNode<T>* find(T _data)const;//print all elementsvoid print_elements()const;//insert fix upvoid insert_fix_up(RBTreeNode<T> *_pNode);private:RBTreeNode<T> *m_pRoot;/*! the root of the R&B tree*/RBTreeNode<T> nil;};template<typename T>void RBTree<T>::print_elements()const{if(m_pRoot == NULL){return ;}std::stack<RBTreeNode<T>*> nStack;nStack.push(m_pRoot);RBTreeNode<T> *tmp = m_pRoot;std::cout<<"All Elements"<<std::endl;while(!nStack.empty()){while(tmp != &nil){tmp = tmp->pLeft;nStack.push(tmp);}nStack.pop();if(!nStack.empty()){tmp = nStack.top();nStack.pop();std::cout<<tmp->data<<std::endl;tmp = tmp->pRight;nStack.push(tmp);}}}//find the tree nodetemplate<typename T>RBTreeNode<T>* RBTree<T>::find(T _data)const{RBTreeNode<T>* pElement = m_pRoot;while(pElement != &nil && pElement->data != _data){if(_data > pElement->data){pElement = pElement->pRight;}else{pElement = pElement->pLeft;}}if(pElement != &nil){return pElement;}return NULL;}//insert a new node into the rb treetemplate<typename T>void RBTree<T>::insert(T data){//create a new nodeRBTreeNode<T>* newNode = new RBTreeNode<T>(data);newNode->color = RED;newNode->pParent = newNode->pRight = newNode->pLeft = &nil;//if current tree is emptyif(m_pRoot == NULL){m_pRoot = newNode;m_pRoot -> color = BLACK;m_pRoot->pParent = &nil;return ;}//pNode for iterating//pInsert for insertionsRBTreeNode<T> *pNode = m_pRoot;RBTreeNode<T> *pInsert = &nil;while(pNode != &nil){if(data > pNode->data){pInsert = pNode;pNode = pNode->pRight;}else if(data < pNode->data){pInsert = pNode;pNode = pNode->pLeft;}else{return ;}}if(pInsert != &nil){if(data > pInsert->data){pInsert->pRight = newNode;}else{pInsert->pLeft = newNode;}newNode->pParent = pInsert;insert_fix_up(newNode);}}template <typename T>void RBTree<T>::insert_fix_up(RBTreeNode<T> *_pNode){RBTreeNode<T>* y;while(_pNode->pParent->color == RED){if(_pNode->pParent == _pNode->pParent->pParent->pLeft){y = _pNode->pParent;if(y->pParent->pRight->color == RED){_pNode->pParent->pParent->pRight->color = BLACK;_pNode->pParent->color = BLACK;_pNode->pParent->pParent->color = RED;_pNode = _pNode->pParent->pParent;}else{if(_pNode->pParent->pRight == _pNode){left_rotate(_pNode->pParent);y = _pNode;_pNode = _pNode->pParent;}y->color = BLACK;y->pParent->color = RED;right_rotate(y->pParent);_pNode = y;}}else if(_pNode->pParent == _pNode->pParent->pParent->pRight){y = _pNode->pParent->pParent->pLeft;if(y ->color == RED){_pNode->pParent->color = BLACK;_pNode->pParent->pParent->color = RED;y->color = BLACK;_pNode = _pNode->pParent->pParent;}else{y = _pNode->pParent;if(_pNode->pParent->pLeft == _pNode){y = _pNode;_pNode = _pNode->pParent;right_rotate(_pNode);}y->color = BLACK;y->pParent->color = RED;left_rotate(y->pParent);_pNode = y;}}}m_pRoot->color = BLACK;}//remove a node from the rb treetemplate<typename T>void RBTree<T>::remove(RBTreeNode<T> *_removeNode){}//left rotate//template<typename T>void RBTree<T>::left_rotate(RBTreeNode<T> *_pNode){RBTreeNode<T> *pRightSon = _pNode->pRight;if(pRightSon == &nil){return ;}//process the parent of _pNodeif(_pNode->pParent != &nil){if(_pNode->pParent->pLeft == _pNode){_pNode->pParent->pLeft = pRightSon;pRightSon->pParent = _pNode->pParent;}else if(_pNode->pParent->pRight == _pNode){_pNode->pParent->pRight = pRightSon;pRightSon->pParent = _pNode->pParent;}}//in this situation, parent of _pNode is the rootelse{m_pRoot = pRightSon;pRightSon->pParent = &nil;}RBTreeNode<T> *pTmp = _pNode->pLeft;pRightSon->pLeft = _pNode;_pNode->pParent = pRightSon;_pNode->pRight = pTmp;pTmp->pParent = _pNode;}//right rotatetemplate<typename T>void RBTree<T>::right_rotate(RBTreeNode<T>* _pNode){RBTreeNode<T> *pLeftSon = _pNode->pLeft;if(pLeftSon == &nil){return ;}if(_pNode->pParent != &nil){if(_pNode->pParent->pLeft == _pNode){_pNode->pParent->pLeft = pLeftSon;pLeftSon->pParent = _pNode->pParent;}else{_pNode->pParent->pRight = pLeftSon;pLeftSon->pParent = _pNode->pParent;}}else{m_pRoot = pLeftSon;pLeftSon->pParent = &nil;}//process the parental relation between _pNode and pLeftSonRBTreeNode<T> *pTmp = pLeftSon->pRight;pLeftSon->pRight = _pNode;_pNode->pParent = pLeftSon;_pNode->pLeft = pTmp;pTmp->pParent = _pNode;}}

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.