红黑树(RBTree)的实现
来源:互联网 发布:轩辕剑符鬼突破数据 编辑:程序博客网 时间:2024/09/21 08:15
红黑树的特点:
1、任意一个结点要么是红色,要么是黑色
2、根结点是黑色
3、一条路径上不能出现两个连续的红色结点
4、从根节点到任一叶子节点的黑色结点个数相同
5、NUL结点默认为黑色结点(可忽略)
插入实现
注意:cur为当前节点,p为父节点,g为祖父节点,u为叔叔节点
【情况一】cur为红,p为红,g为黑,u存在且为红则将p,u改为黑,g改为红,然后把g当成cur,继续向上调整。
【情况二】cur为红,p为红,g为黑,u不存在/u为黑p为g的左孩子,cur为p的左孩子,则进行右单旋转;相反,p为g的右孩子,cur为p的右孩子,则进行左单旋转p、g变色--p变黑,g变红
【情况三】cur为红,p为红,g为黑,u不存在/u为黑p为g的左孩子,cur为p的右孩子,则针对p做左单旋转;相反,p为g的右孩子,cur为p的左孩子,则针对p做右单旋转则转换成了情况2
#pragma once#include<iostream>using namespace std;enum Color{RED,BLACK};template<class K, class V>struct RBTreeNode{RBTreeNode(const K & key,const V & value,Color color = RED):_value(value),_key(key),_pLeft(NULL),_pRight(NULL),_pParent(NULL),_color(color){}K _key;V _value;RBTreeNode<K,V> * _pLeft;RBTreeNode<K,V> *_pRight;RBTreeNode<K,V> *_pParent;Color _color; //节点的颜色。};//红黑树迭代器实现template<class K, class V, class Ref, class Ptr>class Iterator{public:typedef RBTreeNode<K,V> Node;typedef Iterator<K,V,Ref,Ptr> Self;Iterator():_pNode(NULL) { }Iterator(Node *Root):_pNode(Root) { }Iterator(const Self & it):_pNode(it._pNode){ }Ref operator*(){return _pNode->_key;}Ptr operator->(){ return &(operator*() );}Self& operator++(){_pNode = Increment();return *this;}Self operator++(int){Self temp(*this);_pNode = Increment();return temp;}Self& operator--(){_pNode = Decrement();return *this;}Self operator--(int){Self temp(*this);_pNode = Decrement();return temp;}bool operator==(const Self & it){return _pNode == it._pNode;}bool operator != (const Self & it){return _pNode != it._pNode;}private:Node* Increment(){Node *pCur = _pNode;if (pCur->_pRight) //当右子树存在,当前节点的下一个节点就是右子树的最左节点。{Node *pRight = pCur->_pRight;while (pRight->_pLeft){pRight = pRight->_pLeft;}pCur = pRight;}else //右子树不存在。{Node *pParent = pCur->_pParent;while (pParent->_pRight == pCur){pCur = pParent;pParent = pParent->_pParent;}if ( pCur->_pRight != pParent) //特殊情况,最后一个节点还能再++,++后指向end().{pCur = pParent;}}return pCur;}Node* Decrement(){Node *pCur = _pNode;if (RED == pCur->_color && pCur->_pParent->_pParent == pNode)//特殊情况在end()的位置pCur = pCur->_pRight;else if (pCur->_pLeft) //当左子树存在,当前节点的下一个节点就是左子树的最右节点。{Node *pLeft = pCur->_pLeft;while (pRight->_pLeft){pRight = pRight->_pLeft;}pCur = pRight;}else //左子树不存在。{Node *pParent = pCur->_pParent;while (pParent->_pLeft == pCur){pCur = pParent;pParent = pParent->_pParent;}pCur = pParent; //第一个节点不能再减了,如果减就是随机值}return pCur;}private:Node *_pNode;};template<class K, class V>class RBTree{typedef RBTreeNode<K, V> Node;typedef Iterator<K,V,K&,K*> Iterator;public:RBTree(): _pHead(NULL){_pHead = new Node(0,0);_pHead->_pLeft = _pHead;_pHead->_pRight = _pHead;}Iterator Begin(){return Iterator(_pHead->_pLeft);}Iterator End(){return Iterator(_pHead);}Node *GetMaxNode(){Node *pCur = GetRoot();while (pCur->_pRight)//不需要判空 在insert中调用 不会为空pCur = pCur->_pRight;return pCur;}Node *GetMinNode(){Node *pCur = GetRoot();while (pCur->_pLeft)//不需要判空 在insert中调用 不会为空pCur = pCur->_pLeft;return pCur;}bool Insert(const K& key, const V& value){Node *& pRoot= GetRoot();if (pRoot == NULL){pRoot = new Node(key,value);pRoot->_color = BLACK;pRoot->_pParent = _pHead;return true;}Node *pCur = pRoot;Node *pParent = NULL;while (pCur){if (key < pCur->_key){pParent = pCur;pCur = pCur->_pLeft;}else if (key == pCur->_key){return false;}else{pParent = pCur;pCur = pCur->_pRight;}}pCur = new Node(key,value);if (key < pParent->_key){pParent->_pLeft = pCur;pCur->_pParent = pParent;}else{pParent->_pRight = pCur;pCur->_pParent = pParent;}//调整颜色。while (pCur != pRoot && pParent->_color == RED ) //根不需要调整,因为退了这个循环直接把根的颜色改成黑色。{Node *garndFather = pParent->_pParent;Node *uncle = NULL;if (pParent == garndFather->_pRight){uncle = garndFather->_pLeft;}elseuncle = garndFather->_pRight;if (uncle != NULL && uncle->_color == RED) //unclue存在且为红{pParent->_color = BLACK;uncle->_color = BLACK;garndFather->_color = RED;}else //u不存在或者u为黑。{if (pParent == garndFather->_pLeft) //父亲是爷爷的左孩子{if (pCur == pParent->_pRight){RotateLeft(pParent);swap(pParent,pCur);}if (pCur == pParent->_pLeft){RotateRight(garndFather);pParent->_color = BLACK;garndFather->_color = RED;}}else //父亲是爷爷的右孩子。{if (pCur == pParent->_pLeft){RotateRight(pParent);swap(pParent,pCur);}if (pCur == pParent->_pRight){RotateLeft(garndFather);pParent->_color = BLACK;garndFather->_color = RED;}}}pCur = garndFather;pParent = pCur->_pParent;}_pHead->_pLeft = GetMinNode();_pHead->_pRight = GetMaxNode();pRoot->_color = BLACK;return true;}void RotateLeft(Node* parent){Node *pparent = parent->_pParent;Node *subR = parent->_pRight;Node *subRL = subR->_pLeft;if(pparent == _pHead){Node *& pRoot = GetRoot();pRoot = subR;}else{if (parent == pparent->_pLeft){pparent->_pLeft = subR;}else{pparent->_pRight = subR;}}subR->_pParent = pparent;subR->_pLeft = parent;parent->_pParent = subR;parent->_pRight = subRL;if (subRL != NULL){subRL->_pParent = parent;}}void RotateRight(Node* parent){Node * subL = parent->_pLeft;Node *subLR = subL->_pRight;Node *pparent = parent->_pParent;if (pparent == _pHead){Node *& pRoot = GetRoot();pRoot = subL;}else{if (parent == pparent->_pLeft){pparent->_pLeft = subL;}else{pparent->_pRight = subL;}}subL->_pParent = pparent;subL->_pRight = parent;parent->_pParent = subL;parent->_pLeft = subLR;if (subLR != NULL){subLR->_pParent = parent;}}void InOrder(){Node *&pRoot = GetRoot();_InOrder(pRoot);}void _InOrder(Node* pRoot){if(pRoot){_InOrder(pRoot->_pLeft);cout<<pRoot->_key<<" ";_InOrder(pRoot->_pRight);}}//检查是不是红黑树bool CheckRBTree(){Node *&pRoot = GetRoot();if (pRoot == NULL){return true;}if (pRoot->_color == RED){return false;}//找到一条路径上黑色节点的个数size_t blackCount = 0;Node *pCur = pRoot;while (pCur){if (pCur->_color == BLACK){blackCount++;}pCur = pCur->_pLeft;}size_t k = 0;return _CheckRBTree(pRoot,blackCount,k);}//每一条路径上的黑色节点都要相等才是红黑树。bool _CheckRBTree(Node* pRoot, const size_t blackCount, size_t k) //这个地方k一定是值的,假设一条路径 黑-红-黑-黑-红-黑-黑-红-黑 这条路径黑色节点个数为6,现在回溯{ // △,假设回溯到这个节点,如果是引用的话,k还是6, if (pRoot == NULL) //如果你想回溯一次减一,但是回溯的节点可能不是黑色节点,所以引用不行{ //值的话,现在就是4了,符号要求return true;}//当出现两个连续的红色节点的时候,可以确定不是红黑树if (pRoot->_pParent && pRoot->_color == RED && pRoot->_pParent->_color == RED){return false;}//如果是黑节点,k++if (pRoot->_color == BLACK){k++;}//如果是叶子节点的话,进行判断k和count是否相等if (pRoot->_pLeft == NULL && pRoot->_pRight == NULL){if (k != blackCount){return false;}}return _CheckRBTree(pRoot->_pLeft,blackCount,k) && _CheckRBTree(pRoot->_pRight,blackCount,k);}private:Node* _pHead; //红黑树加上一个头节点进行迭代器操作(头节点的左孩子指向红黑树的最小值,右孩子指向最大值,parent域指向根节点)private:Node * & GetRoot() {return _pHead->_pParent;}};
#include "RBTree.h"void Test(){//int a[] = {10, 8, 7, 15, 5, 6, 11, 13, 12};int a[] = {15,14,13,12,11,10,9,8,7,6,5,1,3,2,1,0};RBTree<int, int> bt;for (size_t idx = 0; idx < sizeof(a)/sizeof(a[0]); ++idx)bt.Insert(a[idx], a[idx]);//bt.InOrder();cout << endl; Iterator<int, int, int&, int *> it = bt.Begin(); //cout << "begin()" << *it <<endl; while (it != bt.End()) { cout << *it << " "; it++; } cout <<endl;//cout << bt.CheckRBTree() <<endl;}int main(){Test();system("pause");return 0;}
红黑树和AVL树的比较
红黑树和AVL树都是高效的平衡二叉树,增删查改的时间复杂度都是O(lg(N))红黑树的不追求完全平衡,保证最长路径不超过最短路径的2倍,相对而言,降低了旋转的要求,所以性能跟AVL树差不多,但是红黑树实现更简单,所以实际运用中红黑树更多。
阅读全文
0 0
- 红黑树(RBTree)的实现
- RBTree-红黑树的实现
- RBTree(红黑树的简单实现)
- 红黑树的简单实现-RBTree
- 红黑树(RBTree)的分析和实现
- RBTree的模拟实现
- 红黑树(RBtree)
- 数据结构-红黑树(RBTree)
- 红黑树(RBTree)
- RBTree(红黑树)
- 二叉平衡树avlTree和红黑树rbTree的java实现
- 红黑树rbtree实现,原汁原味nginx。加深理解!
- 红黑树-RBTree
- RBTree红黑树
- RBTree----红黑树
- RBTree(红黑树)
- 红黑树--RBTree
- 红黑树【RBTree】
- 对比指向文字常量区的指针和数组
- 网址收藏---学习,及工具下载
- boost::filesystem 常用方法
- leetcode题解c++ | 25. Reverse Nodes in k-Group
- 【笔记】shiro中的Password加密设置:
- 红黑树(RBTree)的实现
- 字符串的分解问题
- Json进一步应用
- 汇编语言showStr测试子程序
- How to create a link in Linux
- 【BFS瞎搜】九宫重排
- LeetCode刷题(C++)——Verify Preorder Serialization of a Binary Tree(Medium)
- CUBEMX stm32f407 使用(USB虚拟串口)
- B骑士旅行