数据结构之红黑树

来源:互联网 发布: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>

          
    博主还在研究红黑树的增删改的实现,水平有限,如有错误请多指正!!!!

0 0
原创粉丝点击