【数据结构】红黑树的插入(Insert)
2016-06-16 11:17
447 查看
前言:
红黑树是一棵二叉搜索树,它在每个节点上增加了一个存储位来表示节点的颜色,可以是Red或Black。通过对任何一条从根到叶子简单路径上的颜色来约束,红黑树保证最长路径不超过最短路径的两倍,因而近似于平衡。
红黑树的基本概念:
红黑树是满足下面红黑性质的二叉搜索树
1. 每个节点,不是红色就是黑色的
2. 根节点是黑色的
3. 如果一个节点是红色的,则它的两个子节点是黑色的(不能有连续的两个红节点)
4. 对每个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点。
5. 每个叶子节点都是黑色的(这里的叶子节点是指的NIL节点(空节点))
红黑树的插入写法要根据红黑树插入的各种情况来分析:
ps:cur为当前节点,p为父节点,g为祖父节点,u为叔叔节点
1.第一种情况
cur为红,p为红,g为黑,u存在且为红
则将p,u改为黑,g改为红,然后把g当成cur,继续向上调整。
2.第二种情况
cur为红,p为红,g为黑,u不存在/u为黑
p为g的左孩子,cur为p的左孩子,则进行右单旋转;相反,p为g的右孩子,cur为p的右孩子,则进行左单旋转
p、g变色--p变黑,g变红
3.第三种情况
cur为红,p为红,g为黑,u不存在/u为黑
p为g的左孩子,cur为p的右孩子,则针对p做左单旋转;相反,p为g的右孩子,cur为p的左孩子,则针对p做右单旋转
则转换成了情况2
上面已经把没种情况列出来了,其他相反的情况类似,反过来写一下就行了,具体细节过程见代码,
红黑树是一棵二叉搜索树,它在每个节点上增加了一个存储位来表示节点的颜色,可以是Red或Black。通过对任何一条从根到叶子简单路径上的颜色来约束,红黑树保证最长路径不超过最短路径的两倍,因而近似于平衡。
红黑树的基本概念:
红黑树是满足下面红黑性质的二叉搜索树
1. 每个节点,不是红色就是黑色的
2. 根节点是黑色的
3. 如果一个节点是红色的,则它的两个子节点是黑色的(不能有连续的两个红节点)
4. 对每个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点。
5. 每个叶子节点都是黑色的(这里的叶子节点是指的NIL节点(空节点))
红黑树的插入写法要根据红黑树插入的各种情况来分析:
ps:cur为当前节点,p为父节点,g为祖父节点,u为叔叔节点
1.第一种情况
cur为红,p为红,g为黑,u存在且为红
则将p,u改为黑,g改为红,然后把g当成cur,继续向上调整。
2.第二种情况
cur为红,p为红,g为黑,u不存在/u为黑
p为g的左孩子,cur为p的左孩子,则进行右单旋转;相反,p为g的右孩子,cur为p的右孩子,则进行左单旋转
p、g变色--p变黑,g变红
3.第三种情况
cur为红,p为红,g为黑,u不存在/u为黑
p为g的左孩子,cur为p的右孩子,则针对p做左单旋转;相反,p为g的右孩子,cur为p的左孩子,则针对p做右单旋转
则转换成了情况2
上面已经把没种情况列出来了,其他相反的情况类似,反过来写一下就行了,具体细节过程见代码,
#ifndef __RBTREE_H__ #define __RBTREE_H__ enum colour { RED, BLACK, }; template<class K,class V> struct RBTreeNode { int _col; K _key; V _value; RBTreeNode<K, V>* _left; RBTreeNode<K, V>* _right; RBTreeNode<K, V>* _parent; RBTreeNode(const K& key, const V& value) :_key(key) , _value(value) , _col(RED) , _left(NULL) , _right(NULL) , _parent(NULL) {} }; 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->_col = BLACK; return true; } Node* parent = NULL; Node* cur = _root; while (cur) { if (cur->_key > key) { parent = cur; cur = cur->_left; } else if (cur->_key < key) { parent = cur; cur = cur->_right; } else return false; } //插入位置 if (parent->_key >key) { cur = new Node(key, value); parent->_left = cur; cur->_parent = parent; } else if (parent->_key < key) { cur = new Node(key, value); parent->_right = cur; cur->_parent = parent; } //插入位置以后,如何调整 while (cur != _root && parent->_col == RED) { Node* grandfather = parent->_parent; Node* uncle = NULL; //左边的情况 if (parent == grandfather->_left) { //情况一 uncle = grandfather->_right; if (uncle && uncle->_col == RED) { //情况1-> 不需要旋转 if (cur == parent->_left) { grandfather->_col = RED; parent->_col = BLACK; uncle->_col = BLACK; cur = grandfather; parent = cur->_parent; } //需要旋转 else if (cur == parent->_right) { RotateL(parent); grandfather->_col = RED; parent->_col = BLACK; uncle->_col = BLACK; cur = grandfather; parent = cur->_parent; } } //情况2,情况3 else if (uncle == NULL || (uncle && uncle->_col == BLACK)) { //情况3 if (cur == parent->_right) { RotateL(parent); } parent->_col = BLACK; grandfather->_col = RED; RotateR(grandfather); break; } } //右边的情况 else if (parent == grandfather->_right) { //情况1 uncle = grandfather->_left; if (uncle && uncle->_col == RED) { //不需要旋转 if (cur == parent->_right) { uncle->_col = BLACK; grandfather->_col = RED; parent->_col = BLACK; cur = grandfather; parent = cur->_parent; } //旋转 else if (cur == parent->_left) { uncle->_col = BLACK; grandfather->_col = RED; parent->_col = BLACK; RotateR(parent); cur = grandfather; parent = cur->_parent; } } else if (uncle == NULL || (uncle && uncle->_col == BLACK)) { //情况2,3 if (cur == parent->_left) { RotateR(parent); } parent->_col = BLACK; grandfather->_col = RED; RotateL(grandfather); break; } } } _root->_col = BLACK; return true; } bool isRBTree() { int blackNodeNum = 0; int curBlackNodeNum = 0; Node* cur = _root; while (cur) { if (cur->_col == BLACK) blackNodeNum++; cur = cur->_left; } return _isRBTree(_root,blackNodeNum,curBlackNodeNum); } void InOrder() { _InOrder(_root); } protected: bool _isRBTree(Node* root,int blackNodeNum,int curBlackNodeNum) { if (root == NULL) return true; if (root->_col == BLACK) curBlackNodeNum++; if (blackNodeNum == curBlackNodeNum) { if (root->_parent == NULL) return true; else if (root->_col == RED && root->_col == root->_parent->_col) { return false; } else { return true; } } return _isRBTree(root->_left, blackNodeNum, curBlackNodeNum) && _isRBTree(root->_right, blackNodeNum, curBlackNodeNum); } void _InOrder(Node* root) { if (root == NULL) return; _InOrder(root->_left); cout << root->_key << " "; _InOrder(root->_right); } void RotateL(Node*& parent) { Node* subR = parent->_right; Node* subRL = subR->_left; parent->_right = subRL; if (subRL) subRL->_parent = parent; subR->_left = parent; subR->_parent = parent->_parent; parent->_parent = subR; parent = subR; if (parent->_parent == NULL) _root = parent; else if (parent->_parent->_key > parent->_key) { parent->_parent->_left = parent; } else if (parent->_key > parent->_parent->_key) { parent->_parent->_right = parent; } } void RotateR(Node*& parent) { Node* subL = parent->_left; Node* subLR = subL->_right; parent->_left = subLR; if (subLR) subLR->_parent = parent; subL->_right = parent; subL->_parent = parent->_parent; parent->_parent = subL; parent = subL; if (parent->_parent == NULL) _root = parent; else if (parent->_parent->_key > parent->_key) { parent->_parent->_left = parent; } else if (parent->_parent->_key < parent->_key) parent->_parent->_right = parent; } protected: Node* _root; }; void testRBtree() { RBTree<int, int> rbt; int arr[8] = { 2, 5, 12, 16, 18, 26, 3, 1 }; for (int i = 0; i < 8; i++) { rbt.Insert(arr[i], i); } rbt.InOrder(); cout << endl; cout << "isRBTree? ->:" << rbt.isRBTree() << endl; } #endif //__RBTREE_H__
相关文章推荐
- 数据结构--‘搜索二叉树’
- 数据结构_P16
- 前端数据结构与算法系列(转)
- Link-Cut Tree学习总结
- 数据结构-01-字符串(String)
- leetcode——Search Insert Position
- leetcode——Search for a Range
- 常见数据结构
- 【排序】直接选择排序
- 数据结构之AVL树
- 数据结构-队列
- 【排序】插入排序
- 浅谈算法和数据结构: 哈希表
- Java数据结构之多项式加法和乘法实现
- 数据结构(主席树,Bit):XTU 1247/COGS 2344. pair-pair
- 数据结构之栈的基本操作
- 数据结构和算法C++语言实现:链表的实现
- 数据结构——构成哈弗曼树的问题
- 数据结构与算法:STL容器
- 循环链表的基本操作