数据结构-红黑树(RB-Tree)
来源:互联网 发布:中国出境旅游数据统计 编辑:程序博客网 时间:2024/05/17 22:17
- 红黑树的概念和性质
红黑树是这样一颗二叉搜索树:树中的每个结点的颜色不是黑色就是红色。可以看作是一颗扩充二叉树。
特性描述如下:
特性1:根结点一定是黑色
特性2:没有连续的两个红色结点
特性3:所有从根结点到叶子结点的路径上都有相同数目的黑色结点
通过保持这三个性质从而使维持一颗红黑树的平衡。
- 红黑书的结点
enum COLOR{ BLACK, RED};//将结点默认为红色,这样如果父节点为黑色就可以直接插入,并且保持路径黑色结点数目相等template<class K,class V>struct RBTNode{ RBTNode<K, V>* _left; RBTNode<K, V>* _right; RBTNode<K, V>* _parent; K _key; V _value; COLOR _col; RBTNode(const K& key,const V& value) :_key(key) , _value(value) , _parent(NULL) , _left(NULL) , _right(NULL) ,``_col(RED) {}};
- 红黑树的搜索
由于每一颗红黑书都是二叉搜索树,在搜索过程中可以使用普通二叉搜索树时所使用的相同算法。不需要对颜色进行判断。
bool Find(const K& key){ if (_root == NULL) return false; Node* cur = _root; while (cur) { if (key < cur->_key) { cur = cur->_left; } else if (key>cur->_key) { cur = cur->_right; } else { return te} } return false; }
- 红黑树的插入
插入出现的情况:
1)首先使用二插搜索树的插入将结点插入到红黑书中,该元素将作为新的叶子结点。
2)如果是空树,则根据特性1,根结点必须为黑色,因为我们默认结点是红色,所以我们需要将结点染成黑色
3)如果不是空树,那我们就要进行一系列旋转,染色,调整操作:
cur为新插入结点,uncle为叔叔节点,pparent为祖父节点。
1-父亲为黑色
直接插入,因为我们结点默认是红色,不会影响树的黑色结点数目。
2-父亲为红色,叔叔为红色
这时我们插入一个结点相当于已经有两个连续红色结点出现,我们需要就行变色处理,将父亲和叔叔的颜色改成黑色,将祖父的颜色改为红色,然后向上回溯调整。
3-父亲为红色,叔叔为红色
这时仅仅变色已经不能使树保持特性,这里还得对树就行旋转操作。
- 旋转一共分为四种情况:
左单旋
void RotateL(Node* parent) { Node* SubR = parent->_right; Node* SubRL = SubR->_left; parent->_right = SubRL; if (SubRL) SubRL->_parent = parent; Node* pparent = parent->_parent; SubR->_left = parent; parent->_parent = SubR; if (pparent == NULL) { _root = SubR; SubR->_parent = NULL; } else { if (parent == pparent->_left) pparent->_left = SubR; else pparent->_right = SubR; } SubR->_parent = pparent; }
右单旋
void RotateR(Node* parent) { Node* SubL = parent->_left; Node* SubLR = SubL->_right; parent->_left = SubLR; if (SubLR) SubLR->_parent = parent; Node* pparent = parent->_parent; SubL->_right = parent; parent->_parent = SubL; if (pparent == NULL) { _root = SubL; _root->_parent = NULL; } else { if (parent == pparent->_left) pparent->_left = SubL; else pparent->_right = SubL; } SubL->_parent = pparent; }
左右双旋
这里我们可以看到先进行左旋
旋转后cur为父结点而parent为子结点,所以我们旋转一次后交换cur和parent(swap(parent,cur))
if (cur == parent->_right) { //左旋 RotateL(parent); std::swap(parent, cur);//因为左旋后cur已经变成父节点,parent为子节点 } RotateR(pparent); pparent->_col = RED; parent->_col = BLACK; break;
右左双旋
if (cur == parent->_left) { RotateR(parent); std::swap(parent, cur); } RotateL(pparent); parent->_col = BLACK; pparent->_col = RED; break;
红黑树的运用–高效的二叉搜索树
C++ STL库 – map
Java 库
linux内核
其他一些库http://www.cnblogs.com/yangecnu/p/Introduce-Red-Black-Tree.html
红黑树和AVL树的比较
红黑树和AVL树都是高效的平衡二叉树, 增删查改的时间复杂度都是O(lg(N))
红黑树的不追求完全平衡, 保证最长路径不超过最短路径的2倍, 相对而言, 降低了旋转的要求, 所以性能会优于AVL树, 所以实际运用
中红黑树更多。
另外关于红黑书的删除:(参考别人的东西)http://www.cnblogs.com/fornever/archive/2011/12/02/2270692.html
http://blog.csdn.net/chenhuajie123/article/details/11951777
整体实现代码:
#include<iostream>using namespace std;enum COLOR{ BLACK, RED};template<class K,class V>struct RBTNode{ RBTNode<K, V>* _left; RBTNode<K, V>* _right; RBTNode<K, V>* _parent; K _key; V _value; COLOR _col; RBTNode(const K& key,const V& value) :_key(key) , _value(value) , _parent(NULL) , _left(NULL) , _right(NULL) , _col(RED) {}};template<class K,class V>class RBTree{ typedef RBTNode<K, V> Node;public: RBTree() :_root(NULL) {} ~RBTree() { _root = _DestoryRBTree(_root); } RBTree(const RBTree<K, V>& r) { _root = _Copy(r._root); } RBTree<K, V> operator=(const RBTree<K, V>& r) { if (this != &r) { Node* tmp = _Copy(r._root); _root = _DestoryRBTree(_root); _root = tmp; } return *this; } bool Find(const K& key) { if (_root == NULL) return false; Node* cur = _root; while (cur) { if (key < cur->_key) { cur = cur->_left; } else if (key>cur->_key) { cur = cur->_right; } else { return true; } } return false; } pair<Node*, bool> Insert(const K& key, const V& value) { if (_root == NULL) { _root = new Node(key, value); _root->_col = BLACK; return make_pair(_root, true); } Node* parent = NULL; Node* cur = _root; while (cur) { if (key < cur->_key) { parent = cur; cur = cur->_left; } else if (key > cur->_key) { parent = cur; cur = cur->_right; } else { return make_pair(cur, false); } } cur = new Node(key, value); Node* node = cur; if (key < parent->_key) { parent->_left = cur; } else { parent->_right = cur; } cur->_parent = parent; //父亲不为空并且为红色进行调整,父亲为黑色不用进行调整 while (parent != NULL&&parent->_col == RED) { Node* pparent = parent->_parent; Node* uncle = NULL; //父亲为红,叔叔也为红,直接变色 if (parent == pparent->_left) { uncle = pparent->_right; if (uncle&&uncle->_col == RED) { parent->_col = uncle->_col = BLACK; pparent->_col = RED; cur = pparent; parent = pparent->_parent; } else//uncle不存在或者uncle为黑色 { if (cur == parent->_right) { //左旋 RotateL(parent); std::swap(parent, cur);//因为左旋后cur已经变成父节点,parent为子节点 } RotateR(pparent); pparent->_col = RED; parent->_col = BLACK; break; } } else//parent==pparent->right { uncle = pparent->_left; if (uncle&&uncle->_col == RED) { uncle->_col = parent->_col = BLACK; pparent->_col = RED; //向上调整 cur = pparent; parent = cur->_parent; } else//uncle不存在或uncle为黑色 { if (cur == parent->_left) { RotateR(parent); std::swap(parent, cur); } RotateL(pparent); parent->_col = BLACK; pparent->_col = RED; break; } } } _root->_col = BLACK; return make_pair(node, true); }protected: Node* _DestoryRBTree(Node* root) { if (root != NULL) { root->_left = _DestoryRBTree(root->_left); root->_right = _DestoryRBTree(root->_right); root = NULL; } return root; } Node* _Copy(Node* root) { Node* newnode; if (root != NULL) { newnode = new Node(root->_key, root->_value); newnode->_left = _Copy(root->_left); newnode->_right = _Copy(root->_right); } return newnode; } void RotateL(Node* parent) { Node* SubR = parent->_right; Node* SubRL = SubR->_left; parent->_right = SubRL; if (SubRL) SubRL->_parent = parent; Node* pparent = parent->_parent; SubR->_left = parent; parent->_parent = SubR; if (pparent == NULL) { _root = SubR; SubR->_parent = NULL; } else { if (parent == pparent->_left) pparent->_left = SubR; else pparent->_right = SubR; } SubR->_parent = pparent; } void RotateR(Node* parent) { Node* SubL = parent->_left; Node* SubLR = SubL->_right; parent->_left = SubLR; if (SubLR) SubLR->_parent = parent; Node* pparent = parent->_parent; SubL->_right = parent; parent->_parent = SubL; if (pparent == NULL) { _root = SubL; _root->_parent = NULL; } else { if (parent == pparent->_left) pparent->_left = SubL; else pparent->_right = SubL; } SubL->_parent = pparent; } void InOrder() { _InOrder(_root); cout << endl; } void _InOrder(Node* root) { if (root == NULL) return; _InOrder(root->_left); cout << root->_key << endl; _InOrder(root->_right); }protected: Node* _root;};
- 数据结构-红黑树(RB-Tree)
- 【数据结构】:红黑树(RB Tree)
- tree, RB-tree(红黑树)
- 数据结构——红黑树(RB-Tree)
- 红黑树原理(RB-Tree Principle)
- RB-tree (红黑树)相关问题
- 红黑树RB-tree
- 红黑树RB-tree
- 红黑树 RB Tree
- RB-tree 红黑树
- STL RB Tree(红黑树)分析
- 非递归学习树结构(六)--RB-Tree(红黑树)
- STL源码剖析——红黑树(RB-tree)
- RB-Tree
- RB-tree
- RB-tree
- RB tree
- [从头学数学] 第261节 Python实现数据结构:红黑树(RB Tree)
- 状态压缩DP
- 控制台连接数据库乱码问题
- Hrbust 2321 Permutation【递推】
- 交换排序之堆排序
- bzoj 2081: [Poi2010]Beads 哈希
- 数据结构-红黑树(RB-Tree)
- codevs 1036 商务旅行
- c语言中网络套接字浅谈
- JZOJ 3737. 【NOI2014模拟7.11】挖宝藏(treasure)
- Map接口,容器比较选择
- 单链表实现一个冒泡排序
- git的使用
- Follow MIT的6.828 Lab1 & Homework:shell
- Java中线程池的使用