RBTree

来源:互联网 发布:多益网络官网手游注册 编辑:程序博客网 时间:2024/05/16 15:45

RBTree--红黑树

一.规则

   1.每一个结点不是红色就是黑色。

2.根结点是黑色。

3.如果一个节点是红色,那它的两个子结点是黑色。(parent结点不能和child节点颜色同为红色)

4对每个节点来说,从该节点到其所有后代的叶子结点的简单路径上,均包含相同数目的黑色结点。

     二.RNTreeNode

enum color{RED,BLACK,};template<class K,class V>struct RBTreeNode{RBTreeNode<K, V>* _parent;RBTreeNode<K, V>* _left;RBTreeNode<K, V>* _right;color _col;K _key;V _value;RBTreeNode(const K& key, const V& value):_parent(NULL), _left(NULL), _right(NULL), _col(RED), _key(key), _value(value){}};

     三.Insert接口

        1.插入节点,依据规则调节颜色。

        2.调节颜色,分为三种情况。

<span style="font-size:14px;">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{cur = new Node(key, value);parent->_right = cur;cur->_parent = parent;}while (cur != _root && parent->_col == RED)  //调节颜色 条件1:保证一定会有父亲结点 条件2:保证一定会有祖父结点{Node* grandfather = parent->_parent;if (parent == grandfather->_left)   //确定uncle节点在祖父节点的左/右{Node* uncle = grandfather->_right;if (uncle && uncle->_col == RED)   //情况1{uncle->_col = BLACK;parent->_col = BLACK;grandfather->_col = RED;cur = grandfather;parent = cur->_parent;}else{/*if (parent->_left == cur){parent->_col = BLACK;grandfather->_col = RED;_RotateR(grandfather);}else{parent->_col = BLACK;grandfather->_col = RED;_RtateL(parent);}*/if (parent->_right == cur)   //情况3 直接转化为情况2{_RotateL(parent);}parent->_col = BLACK;grandfather->_col = RED;_RotateR(grandfather);    //情况2break;}}else                         </span><span style="font-size:10px;">//<span style="font-family: Arial, Helvetica, sans-serif;">parent == grandfather->_right   同样分三种情况</span></span><span style="font-size:14px;">{Node* uncle = grandfather->_left;if (uncle && uncle->_col == RED){uncle->_col = BLACK;parent->_col = BLACK;grandfather->_col = RED;cur = grandfather;parent = cur->_parent;}else{if (parent->_left == cur){_RotateR(parent);}parent->_col = BLACK;grandfather->_col = RED;_RotateL(grandfather);break;}}}_root->_col = BLACK;}</span>


       四.Check接口

bool Check(){int blacknum = 0;//记录一条路径(这里计算的是最左路)黑色节点的个数 int blacknumcur = 0; //记录当前结点到根节点之间的黑色节点个数Node* cur = _root;while (cur){if (cur->_col == BLACK){++blacknum;}cur = cur->_left;}return _Check(_root, blacknum, blacknumcur);}bool _Check(Node* root, int blacknum, int blacknumcur){if (root == NULL){return true;}if (root->_col == BLACK){++blacknumcur;}else{if (root->_parent && root->_parent->_col == RED)   //父亲结点和子结点同为红色{cout << "Not balance!  ALL RED" << root->_key <<endl;return false;}}if (root->_left == NULL && root->_right == NULL){if (blacknum == blacknumcur){return true;}else   //黑色数量不等{cout << "Not balance!" << root->_key <<endl;return false;}}return _Check(root->_left, blacknum, blacknumcur) && _Check(root->_right, blacknum, blacknumcur); //递归求每条路径}


    五.代码实现


#pragma once#include<iostream>using namespace std;enum color{RED,BLACK,};template<class K,class V>struct RBTreeNode{RBTreeNode<K, V>* _parent;RBTreeNode<K, V>* _left;RBTreeNode<K, V>* _right;color _col;K _key;V _value;RBTreeNode(const K& key, const V& value):_parent(NULL), _left(NULL), _right(NULL), _col(RED), _key(key), _value(value){}};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{cur = new Node(key, value);parent->_right = cur;cur->_parent = parent;}while (cur != _root && parent->_col == RED){Node* grandfather = parent->_parent;if (parent == grandfather->_left){Node* uncle = grandfather->_right;if (uncle && uncle->_col == RED){uncle->_col = BLACK;parent->_col = BLACK;grandfather->_col = RED;cur = grandfather;parent = cur->_parent;}else{/*if (parent->_left == cur){parent->_col = BLACK;grandfather->_col = RED;_RotateR(grandfather);}else{parent->_col = BLACK;grandfather->_col = RED;_RtateL(parent);}*/if (parent->_right == cur){_RotateL(parent);}parent->_col = BLACK;grandfather->_col = RED;_RotateR(grandfather);break;}}else{Node* uncle = grandfather->_left;if (uncle && uncle->_col == RED){uncle->_col = BLACK;parent->_col = BLACK;grandfather->_col = RED;cur = grandfather;parent = cur->_parent;}else{if (parent->_left == cur){_RotateR(parent);}parent->_col = BLACK;grandfather->_col = RED;_RotateL(grandfather);break;}}}_root->_col = BLACK;}void InOrder(){_InOrder(_root);cout << endl;}bool Check(){int blacknum = 0;//记录一条路径(这里计算的是最左路)黑色节点的个数 int blacknumcur = 0; //记录当前结点到根节点之间的黑色节点个数Node* cur = _root;while (cur){if (cur->_col == BLACK){++blacknum;}cur = cur->_left;}return _Check(_root, blacknum, blacknumcur);}protected:bool _Check(Node* root, int blacknum, int blacknumcur){if (root == NULL){return true;}if (root->_col == BLACK){++blacknumcur;}else{if (root->_parent && root->_parent->_col == RED){cout << "Not balance!  ALL RED" << root->_key <<endl;return false;}}if (root->_left == NULL && root->_right == NULL){if (blacknum == blacknumcur){return true;}else{cout << "Not balance!" << root->_key <<endl;return false;}}return _Check(root->_left, blacknum, blacknumcur) && _Check(root->_right, blacknum, blacknumcur);}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* subRleft = subR->_left;parent->_right = subRleft;if (subRleft){subRleft->_parent = parent;}subR->_left = parent;subR->_parent = parent->_parent;parent->_parent = subR;parent = subR;if (parent->_parent == NULL){_root = parent;}else{Node* ppNode = parent->_parent;if (ppNode->_key > parent->_key){ppNode->_left = parent;}else{ppNode->_right = parent;}}}void _RotateR(Node*& parent){Node* subL = parent->_left;Node* subLright = subL->_right;parent->_left = subLright;if (subLright)subLright->_parent = parent;subL->_right = parent;subL->_parent = parent->_parent;parent->_parent = subL;parent = subL;if (parent->_parent == NULL){_root = parent;}else{Node* ppNode = parent->_parent;if (ppNode->_key > parent->_key){ppNode->_left = parent;}else{ppNode->_right = parent;}}}protected:Node* _root;};void TestRBTree(){int a[] = { 1, 4, 6, 8, 0, 2, 3, 5, 9, 7 };RBTree<int, int> rb;for (size_t i = 0; i < sizeof(a) / sizeof(a[0]); ++i){rb.Insert(a[i], i);}rb.InOrder();rb.Check();}


    以上就是本人在学习过程中的一些经验总结。当然,本人能力有限,难免会有纰漏,希望大家可以指正。


2 0