红黑树>
在之前实现了AVL树,其实红黑树和AVL树都是高效且平衡的二叉搜索树,增删查改的时间复杂度都是O(lg N).但是在实际应用中红黑树的应用最多,比如C++STL库--map/set,Java库,Linux内核以及其他的一些库里都用到了红黑树,这是因为红黑树是不追求完全平衡的是一种近似平衡的二叉树,保证最长路径不超过最短路径的二倍,相对于AVL树来说降低了旋转的要求,所以性能会优于AVL树(这篇文章主要介绍红黑树的插入).
在上面提到了红黑树的特性是保证最长路径不超过最短路径的二倍,那仫为什仫满足这样的要求就是红黑树了呢?让我先来介绍一下红黑树的性质>
1).每个结点不是红色就是黑色.
2).根结点是黑色的.
3).如果一个结点是红色的,则它的两个子节点是黑色的(不存在连续的红结点).
4).对每个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点(每条路径上黑色结点的数量相等)
5).每个叶子结点都是黑色的(这里的叶子结点指的是空结点).
假设有这样的一棵树它的所有节点都是黑色的,而且满足红黑树的特性,此时再次插入新的结点要重新满足红黑树的特性4,我们只能插入红色结点,而且插入新的红色结点为了满足特性3,只能在黑色结点之间插入新的红色结点,此时最长路径上的结点数量恰好满足不超过最短路径的两倍.
红黑树的插入>
为了满足红黑树的特性4,所以新插入的结点的颜色必须为红色.
当前结点cur为红色,parent为红色,则必然存在祖父结点.因为不能存在连续的红色结点,所以祖父结点的颜色一定是黑色的.根据uncle是否存在以及uncle结点的颜色来进行不同的处理.
(1).uncle存在且uncle为红.
(2).uncle不存在或者uncle为黑色.
通过上图观察可得情况3和情况2类似,可以将情况3先进行左单旋变成和情况2类似的情况再进行右单旋,最后达到处理的效果.
在进行双旋的时候,因为双旋是分成单旋来完成的所以双旋完成第一次单旋后要修改parent和cur指针否则就会导致丢失结点的现象.
(3).当parent->_right == cur时和上述情况类似,在这里我就不多加叙述了.
代码实现区>
- #pragma once
- enum Colour
- {
- RED,
- BLACK
- };
- template<class K,class V>
- struct RBTreeNode
- {
- K _key;
- V _value;
- RBTreeNode<K,V>* _left;
- RBTreeNode<K,V>* _right;
- RBTreeNode<K,V>* _parent;
- Colour _color;
- RBTreeNode(const K& key,const V& value)
- :_key(key)
- ,_value(value)
- ,_left(NULL)
- ,_right(NULL)
- ,_parent(NULL)
- ,_color(RED)
- {}
- };
- template<class K,class V>
- class RBTree
- {
- typedef RBTreeNode<K,V> Node;
- public:
- RBTree()
- :_root(NULL)
- {}
- bool Insert(const K& key,const V& value)
- {
- if(_root == NULL)
- {
- _root=new Node(key,value);
- _root->_color=BLACK;
- return true;
- }
- Node *parent=NULL;
- Node *cur=_root;
- while (cur)
- {
- if (cur->_key < key)
- {
- parent=cur;
- cur=cur->_right;
- }
- else if (cur->_key > key)
- {
- parent=cur;
- cur=cur->_left;
- }
- else
- return false;
- }
- cur=new Node(key,value);
- cur->_parent=parent;
- if(parent->_key < key)
- parent->_right=cur;
- else
- parent->_left=cur;
- while (cur != _root && parent->_color == RED) //保证有父亲和祖父
- {
- Node *grandfather=parent->_parent;
- if (grandfather->_left == parent)
- {
- Node *uncle=grandfather->_right;
- if (uncle && uncle->_color == RED) //情况1
- {
- parent->_color=uncle->_color=BLACK;
- grandfather->_color=RED;
- //继续向上调整
- cur=grandfather;
- parent=cur->_parent;
- }
- else //uncle不存在或者uncle为黑色
- {
- if (parent->_right == cur) //情况3
- {
- _RotateL(parent);
- //第一次旋转完成后更新parent和cur
- swap(parent,cur);
- }
- _RotateR(grandfather); //情况2
- grandfather->_color=RED;
- parent->_color=BLACK;
- break;
- }
- }
- else //grandfather->_right == parent
- {
- Node *uncle=grandfather->_left;
- if(uncle && uncle->_color == RED)
- {
- parent->_color=uncle->_color=BLACK;
- grandfather->_color=RED;
- cur=grandfather;
- parent=cur->_parent;
- }
- else //uncle不存在或者uncle为黑色
- {
- if (parent->_left == cur)
- {
- _RotateR(parent);
- swap(parent,cur);
- }
- _RotateL(grandfather);
- grandfather->_color=RED;
- parent->_color=BLACK;
- break;
- }
- }
- }
- _root->_color=BLACK;
- return true;
- }
- bool Find(const K& key)
- {
- if(_root == NULL)
- return false;
- Node *cur=_root;
- while (cur)
- {
- if(cur->_key < key)
- cur=cur->_right;
- else if(cur->_key > key)
- cur=cur->_left;
- else
- return true;
- }
- return false;
- }
- void InOrder()
- {
- _InOrder(_root);
- cout<<endl;
- }
- bool IsRBTree()
- {
- if(_root == NULL)
- return true;
- if(_root->_color == RED) //判断根结点是否是黑色
- return false;
- int count=0;
- Node *cur=_root;
- while (cur)
- {
- if(cur->_color == BLACK)
- count++;
- cur=cur->_left;
- }
- int k=0;
- return _IsRBTree(_root,count,k);
- }
- ~RBTree()
- {
- _Destroy(_root);
- }
- protected:
- bool _IsRBTree(Node *root,const int count,int k)
- {
- if(root == NULL)
- return true;
- if (root->_color == RED && root->_parent->_color == RED)
- {
- cout<<"存在连续的红结点:"<<root->_key<<endl;
- return false;
- }
- if(root->_color == BLACK)
- ++k;
- if (root->_left == NULL && root->_right == NULL)
- {
- if(count != k)
- {
- cout<<"黑色结点的数量不等"<<root->_key<<endl;
- return false;
- }
- }
- return _IsRBTree(root->_left,count,k) && _IsRBTree(root->_right,count,k);
- }
- void _RotateL(Node *parent)
- {
- Node *subR=parent->_right;
- Node *subRL=subR->_left;
- parent->_right=subRL;
- if(subRL)
- subRL->_parent=parent;
- subR->_left=parent;
- Node *ppNode=parent->_parent;
- parent->_parent=subR;
- if (ppNode == NULL)
- {
- _root=subR;
- subR->_parent=NULL;
- }
- else
- {
- if(ppNode->_left == parent)
- ppNode->_left=subR;
- else
- ppNode->_right=subR;
- subR->_parent=ppNode;
- }
- }
- void _RotateR(Node *parent)
- {
- Node *subL=parent->_left;
- Node *subLR=subL->_right;
- parent->_left=subLR;
- if(subLR)
- subLR->_parent=parent;
- subL->_right=parent;
- Node *ppNode=parent->_parent;
- parent->_parent=subL;
- if (ppNode == NULL)
- {
- _root=subL;
- subL->_parent=NULL;
- }
- else
- {
- if(ppNode->_left == parent)
- ppNode->_left=subL;
- else
- ppNode->_right=subL;
- subL->_parent=ppNode;
- }
- }
- void _InOrder(Node *root)
- {
- if(root == NULL)
- return ;
- _InOrder(root->_left);
- cout<<root->_key<<" ";
- _InOrder(root->_right);
- }
- void _Destroy(Node *&root)
- {
- if(root == NULL)
- return ;
- Node *cur=root;
- if (cur)
- {
- _Destroy(cur->_left);
- _Destroy(cur->_right);
- delete cur;
- cur=NULL;
- }
- }
- protected:
- Node *_root;
- };