数据结构之红黑树
来源:互联网 发布:win10提速 优化 编辑:程序博客网 时间:2024/06/05 16:51
一直觉得数据结构中最难以搞懂的结构之一就是红黑树了。所以一开始就对红黑树有一股“敬畏感”,所以在学习红黑树的时候在网上查找了很多资料。但是网上的资料在讲解时条理不清,有的只是点甚至一笔带过,树的变化也没有体现出来。自己总结了好久才把它给搞定,再此,向大家分享一下个人的思路。
首先,我们要知道红黑树的规则:
性质1. 节点是红色或黑色。
性质2. 根是黑色。
性质3. 所有叶子都是黑色(叶子是NIL节点)。
性质4. 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)
性质5. 从任一节点到其每个叶子的所有简单路径 都包含相同数目的黑色节点。
咋一看红黑树的规则很多,要想所有节点都满足这5条性质还是有难度的,但是其实这5条性质是相互依赖的,只要我们掌握一些方法去调整子树,整棵树将会满足这些性质(在这里不得不感叹前辈们的智慧真的是相当的牛)。
在这里博主主要讨论的是红黑树的插入操作:
红黑树的插入节点是不难的,它的插入操作类似于二叉搜索树,在这里就略过了,但是有一点要说明,每个新插入的结点默认都是红色的,所以只要心插入的结点的父节点是黑色,那么我们就无需调整树结构,红黑树并不是AVL平衡二叉树那么的严格。这也是红黑树应用广泛的原因。
总结起来新插入节点可以分为以下几种情况:(cur为新插入的结点,root为根节点,parent为cur的父节点,uncle为parent的兄弟结点,grandpa为parent的父节点)
1.root为空
将新结点给root,并将结点改为黑色(性质2)。
2.parent的颜色为黑色
直接插入cur(直接就满足所有条件)
3.parent的颜色为红色
此情况下有可以分为以下几种情况:
1.cur为红,parent为红,grandpa为黑,uncle存在且为红
调整颜色:grandpa为红,uncle为黑,parent为黑(注意不管是何种情况,cur的颜色一致不变,为红)
2.cur为红,parent为红,grandpa为黑,uncle不存在或者为黑调整树和结点颜色:(一)grandpa->left==parent parent->left==cur。
右旋转,parent为黑,grandpa为红,cur为红
(二)grandpa->right==parent parent->right=cur。
左旋转,parent为黑,grandpa为红
(三)grandpa->_left == parent,parent->_right == cur
左右双旋,cur为黑,grandpa为红
(四)grandpa->right == parent,parent->left == cur
右左双旋,cur为黑,grandpa为红
<span style="font-size:14px;">#pragma once#include<iostream>using namespace std;enum Color{RED,BLACK};template<class K,class V>struct RBNode{RBNode<K, V>* _left;RBNode<K, V>* _right;RBNode<K, V>* _parent;K _key;V _value;Color _color;RBNode(const K& key, const V& value):_left(NULL), _right(NULL), _parent(NULL), _key(key), _value(value), _color(RED){}};template<class K,class V>class RBTree{public:typedef RBNode<K, V> Node;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* cur = _root;Node* parent = NULL;while (cur){parent = cur;if (cur->_key > key)cur = cur->_left;else if (cur->_key < key)cur = cur->_right;elsereturn false;}cur = new Node(key, value);cur->_parent = parent;if (parent->_key > key){parent->_left = cur;}else{parent->_right = cur;}if (parent->_color == BLACK)//如果插入的结点的父节点是黑色,那么不必调整return true;while (cur != _root &&cur->_color == RED&& parent->_color == RED)//只有当parent为红,cur为红时调整,cur!=root保证parent不为空{Node* grandpa = parent->_parent;Node* uncle = NULL;if (parent == grandpa->_left)uncle = grandpa->_right;elseuncle = grandpa->_left;if (uncle&&uncle->_color == RED){grandpa->_color = RED;uncle->_color = BLACK;parent->_color = BLACK;}else{if (grandpa->_left == parent&&parent->_left == cur){_RotateR(grandpa);grandpa->_color = RED;parent->_color = BLACK;cur->_color = RED;}if (grandpa->_right == parent&&parent->_right == cur){_RotateL(grandpa);parent->_color = BLACK;grandpa->_color = RED;}if (grandpa->_left == parent&&parent->_right == cur){_RotateLR(grandpa);cur->_color = BLACK;grandpa->_color = RED;}if (grandpa->_right == parent&&parent->_left == cur){_RotateRL(grandpa);cur->_color = BLACK;grandpa->_color = RED;}}_root->_color = BLACK;//每次调整完树都要把根置为黑色(性质2)cur = parent;parent = cur->_parent;}_root->_color = BLACK;return true;}</span><pre name="code" class="cpp"><span style="font-size:14px;">protected:void _RotateR(Node*& parent)//右旋转{Node* subL = parent->_left;Node* subLR = subL->_right;Node* pNode = parent->_parent;parent->_left = subLR;if (subLR){subLR->_parent = parent;}subL->_right = parent;parent->_parent = subL;parent = subL;subL->_parent = pNode;if (pNode == NULL){_root = subL;}else{if (pNode->_key > subL->_key){pNode->_left = subL;}else{pNode->_right = subL;}}}void _RotateL(Node*& parent)//左旋转{Node* subR = parent->_right;Node* subRL = subR->_left;Node* pNode = parent->_parent;parent->_right = subRL;if (subRL){subRL->_parent = parent;}subR->_left = parent;parent->_parent = subR;parent = subR;parent->_parent = pNode;if (pNode == NULL){_root = subR;}else{if (pNode->_key > subR->_key){pNode->_left = subR;}else{pNode->_right = subR;}}}void _RotateRL(Node* parent)//右左双旋{_RotateR(parent->_right);_RotateL(parent);}void _RotateLR(Node* parent)//左右双旋{_RotateL(parent->_left);_RotateR(parent);}protected:Node* _root;};</span>
博主还在研究红黑树的增删改的实现,水平有限,如有错误请多指正!!!!
- 内核数据结构之红黑树
- 数据结构之红黑树
- 数据结构之红黑树
- 【转】数据结构之红黑树
- 数据结构之红黑树
- 数据结构之红黑树
- 数据结构之(红黑树)
- 数据结构之红黑树
- 数据结构树之红黑树
- 数据结构之红黑树
- 数据结构之红黑树
- 数据结构之红黑树
- 数据结构之红黑树
- 数据结构之红黑树
- 数据结构之红黑树
- 数据结构之红黑树
- 数据结构之红黑树
- 数据结构之红黑树
- ios开发中的runloop
- Go语言gdb调试打印全局变量
- Python的第一个实用小程序--IDE下翻译
- English_study v
- HTML5 应用程序缓存
- 数据结构之红黑树
- IOS UIScrollView
- Android Studio创建app问题: Install repository and sync project等
- 类的静态成员函数带来了什么好处,应该在什么时候使用?
- 手动绘制一个简单的圆
- openfire的启动流程
- 插件平台的类加载机制
- JavaScript中解决浏览器兼容性问题
- qt编译时, make:警告:检测时钟错误。您的创建可能是不完整的。