【数据结构】中的红黑树-RBTree

来源:互联网 发布:软件模块设计 编辑:程序博客网 时间:2024/05/20 11:23

1,概念:

红黑树是一种自平衡二叉查找树,是在计算机科学中用到的一种数据结构,典型的用途是实现关联数组。它是在1972年由鲁道夫·贝尔发明的,他称之为"对称二叉B树",它现代的名字是在 Leo J. Guibas 和 Robert Sedgewick 于1978年写的一篇论文中获得的。它是复杂的,但它的操作有着良好的最坏情况运行时间,并且在实践中是高效的: 它可以在O(log )时间内做查找,插入和删除,这里的是树中元素的数目。

2,性质:

红黑树是每个节点都带有颜色属性的二叉查找树,颜色或红色或黑色。在二叉查找树强制一般要求以外,对于任何有效的红黑树我们增加了如下的额外要求:

     (1),节点不是红色就是黑色

     (2),根节点必须是黑色的

     (3),一个节点是红色的,子节点必须为黑色的,也就是说,没有连续的红色节点,但是可以有连续的黑节点

     (4),每条路径从根节点到叶子节点的黑色节点的数目是相同的

3,代码实现:

插入:

bool Insert(const K& key, const V& value){//1,当红黑树为空的时候,则插入的节点就为根节点,并且根节点的颜色置为黑色if (_root == NULL){_root = new Node<key, value>;_root->_color = BLACK;return true;}//2,红黑树的根节点不为空Node* cur = _root;Node* parent = NULL;//当cur不为NULL的时候,比较cur和key的大小,找到插入key的合适位置while (cur){if (cur->_key > key){parent = cur;cur = cur->_left;}else if (cur->_key < key){parent = cur;cur = cur->_right;}else{return false;}}cur = new Node<key, value>;//让cur指向新建的节点if (parent->_key < key){parent->_right = cur;}else{parent->_left = cur;}cur->_parent = parent;//_root->_color = BLACK;//将根节点置为黑色while (parent&&parent->_color == RED)// {Node* grandfather = parent->_parent;if (parent == grandfather->_left)//父亲节点为{Node* uncle = grandfather->_right;if (uncle&&uncle->_color == RED)//如果叔叔存在,并且叔叔的颜色是红色{parent->_color = uncle->_color = BLACK;//将parent和叔叔的颜色变为黑色grandfather->_color = RED;//将grandfather的颜色置为红色cur = grandfather;//让cur指向parent,继续向上遍历,检查cur为红色的节点时,它的parent是否为红,再进行变色处理parent = cur->_parent;//让cur的父亲指向为父亲节点}else//叔叔节点不存在或者叔叔节点的颜色为黑色{if (cur == parent->_right){RotateL(parent);}RotateR(grandfather);parent->_color = BLACK;grandfather->_color = RED;}break;}else//父亲节点是祖父节点的右节点{Node* uncle = grandfather->_left;if (uncle&&uncle->_color == RED)//如果{parent->_color = uncle->_color = BLACK;//parent和uncle的颜色置为黑色grandfather->_color = RED;//祖父的颜色置为红色cur = grandfather;//cur指向祖父parent = cur->_parent;//parent指向cur的父节点}else if (cur = parent->_left){RotateR(parent);}RotateL(grandfather);parent->_color = BLACK;grandfather->_color = RED;break;}}_root->_color = BLACK;return true;}

判断是否为红黑树 :

bool IsBlance(){if (_root == NULL){return true;}if (_root->_color == RED){return false;}int blackNum = 0;Node* left = _root;while (left){if (left->_color == BLACK){++blackNum;}left = left->_left;}int num = 0;return _IsBalance(_root, num, blackNum);}bool _IsBalance(Node* root, int blackNum, int num){if (root == NULL){if (num != blackNum){cout << "黑色节点数目不相等" << endl;return false;}else{return true;}}if (root->_color == RED&&root->_parent->_color==RED){cout << "存在连续红节点" << root->_key << endl;return false;}if (root->_color){++num;}return _IsBalance(root->_left, num, blackNum) && _IsBalance(root->_right, num, blackNum);}

左右旋转:

void RotateL(Node* parent){Node* subR = _root->_right;Node* subRL = _root->_left;parent->_right = subRL;if (subRL){subRL->_parent = parent;}subR->_left = parent;Node* ppNode = parent->_parent;parent->_parent = subR;if (ppNode==NULL){subR->_parent = NULL;_root = subR;}else{if (ppNode->_left == parent){ppNode->_left = subR;}else{ppNode->_right = subR;}subR->_parent = ppNode;}}void RotateR(Node* parent){Node* subL = parent->_left;Node* subLR = subL->_right;parent->_right = subLR;if (subLR){subLR->_parent = parent;}Node* ppNode = parent->_parent;subL->_right = parent;parent->_parent = subL;if (ppNode){_root = subL;subL->_parent = NULL;}else{if (ppNode->_left == parent){ppNode->_left = subL;}else{ppNode->_right = subL;}subL->_right == ppNode;}}
下面是完整的代码:

#include<iostream>using namespace std;#include<string>#include<vector>//const int RED = 0;//const int BLACK = 1;enum Color{RED,BLACK,};template<class K,class V>struct RBTreeNode{K _key;V _value;Color _color;RBTreeNode<K, V> *_left;RBTreeNode<K, V> *_right;RBTreeNode<K, V> *_parent;RBTreeNode(const K& key, const V& value):_key(key), _value(value), _color(RED), _right(NULL), _left(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){//1,当红黑树为空的时候,则插入的节点就为根节点,并且根节点的颜色置为黑色if (_root == NULL){_root = new Node<key, value>;_root->_color = BLACK;return true;}//2,红黑树的根节点不为空Node* cur = _root;Node* parent = NULL;//当cur不为NULL的时候,比较cur和key的大小,找到插入key的合适位置while (cur){if (cur->_key > key){parent = cur;cur = cur->_left;}else if (cur->_key < key){parent = cur;cur = cur->_right;}else{return false;}}cur = new Node<key, value>;//让cur指向新建的节点if (parent->_key < key){parent->_right = cur;}else{parent->_left = cur;}cur->_parent = parent;//_root->_color = BLACK;//将根节点置为黑色while (parent&&parent->_color == RED)// {Node* grandfather = parent->_parent;if (parent == grandfather->_left)//父亲节点为{Node* uncle = grandfather->_right;if (uncle&&uncle->_color == RED)//如果叔叔存在,并且叔叔的颜色是红色{parent->_color = uncle->_color = BLACK;//将parent和叔叔的颜色变为黑色grandfather->_color = RED;//将grandfather的颜色置为红色cur = grandfather;//让cur指向parent,继续向上遍历,检查cur为红色的节点时,它的parent是否为红,再进行变色处理parent = cur->_parent;//让cur的父亲指向为父亲节点}else//叔叔节点不存在或者叔叔节点的颜色为黑色{if (cur == parent->_right){RotateL(parent);}RotateR(grandfather);parent->_color = BLACK;grandfather->_color = RED;}break;}else//父亲节点是祖父节点的右节点{Node* uncle = grandfather->_left;if (uncle&&uncle->_color == RED)//如果{parent->_color = uncle->_color = BLACK;//parent和uncle的颜色置为黑色grandfather->_color = RED;//祖父的颜色置为红色cur = grandfather;//cur指向祖父parent = cur->_parent;//parent指向cur的父节点}else if (cur = parent->_left){RotateR(parent);}RotateL(grandfather);parent->_color = BLACK;grandfather->_color = RED;break;}}_root->_color = BLACK;return true;}void InOrder(){_InOrder(_root);cout << endl;}bool IsBlance(){if (_root == NULL){return true;}if (_root->_color == RED){return false;}int blackNum = 0;Node* left = _root;while (left){if (left->_color == BLACK){++blackNum;}left = left->_left;}int num = 0;return _IsBalance(_root, num, blackNum);}protected:void RotateL(Node* parent){Node* subR = _root->_right;Node* subRL = _root->_left;parent->_right = subRL;if (subRL){subRL->_parent = parent;}subR->_left = parent;Node* ppNode = parent->_parent;parent->_parent = subR;if (ppNode==NULL){subR->_parent = NULL;_root = subR;}else{if (ppNode->_left == parent){ppNode->_left = subR;}else{ppNode->_right = subR;}subR->_parent = ppNode;}}void RotateR(Node* parent){Node* subL = parent->_left;Node* subLR = subL->_right;parent->_right = subLR;if (subLR){subLR->_parent = parent;}Node* ppNode = parent->_parent;subL->_right = parent;parent->_parent = subL;if (ppNode){_root = subL;subL->_parent = NULL;}else{if (ppNode->_left == parent){ppNode->_left = subL;}else{ppNode->_right = subL;}subL->_right == ppNode;}}void _InOrder(Node* root){if (root == NULL){return;}_InOrder(root->_left);cout << root->_key << " ";_InOrder(root->_right);}bool _IsBalance(Node* root, int blackNum, int num){if (root == NULL){if (num != blackNum){cout << "黑色节点数目不相等" << endl;return false;}else{return true;}}if (root->_color == RED&&root->_parent->_color==RED){cout << "存在连续红节点" << root->_key << endl;return false;}if (root->_color){++num;}return _IsBalance(root->_left, num, blackNum) && _IsBalance(root->_right, num, blackNum);}protected:Node* _root;};void Test(){int a[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };RBTree<int, int> tree;for (int i = 0; i < 9; i++){tree.Insert(a[i], i);}cout << tree.IsBlance() << endl;tree.InOrder();}int main(){Test();system("pause");return 0;}




1 0