【数据结构】红黑树

来源:互联网 发布:淘宝网买男鞋 编辑:程序博客网 时间:2024/06/07 07:05
红黑树是一棵二叉搜索树,它在每个节点上增加了一个存储位来表示节点的颜色,可以是Red或Black。通过对任何一条从根到叶子简单路径上的颜色来约束,红黑树保证最长路径不超过最短路径的两倍,因而近似于平衡。
  • 红黑树是满足下面红黑性质的二叉搜索树
  1. 每个节点,不是红色就是黑色的
  2. 根节点是黑色的
  3. 如果一个节点是红色的,则它的两个子节点是黑色的(没有连续的红节点)
  4. 对每个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点。(每条路径的黑色节点的数量相等)
Test.cpp(主函数)

#include<iostream>using namespace std;#include"RBTree.h"int main(){TestTree();getchar();return 0;}
RBTree.h(头文件)
#pragma onceenum Color{RED,BLACK,};template<class K,class V>struct RBTreeNode{K _key;V _value;RBTreeNode<K,V>* _left;RBTreeNode<K,V>* _right;RBTreeNode<K,V>* _parent;Color _color;RBTreeNode(const K& key,const V& value):_key(key),_value(value),_left(NULL),_right(NULL),_parent(NULL),_color(RED){}};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->_color = BLACK;return true;}Node* cur = _root;Node* parent = NULL;while(cur){if(cur->_key < key){parent = cur;cur = cur->_right;}else if(cur->_key > key){parent = cur;cur = cur->_left;}else{return false;}}cur = new Node(key,value);if(parent->_key > key){parent->_left = cur;cur->_parent = parent;}else if(parent->_key < key){parent->_right = cur;cur->_parent = parent;}// 调整颜色while(cur != _root && parent->_color == RED){Node* grandfather = parent->_parent;if (parent == grandfather->_left){Node* uncle = grandfather->_right;// 情况1:cur为红,p为红,g为黑,u存在且为红if (uncle && uncle->_color == RED){parent->_color = BLACK;uncle->_color = BLACK;grandfather->_color = RED;cur = grandfather;parent = cur->_parent;}//叔叔不存在,存在且为黑色else if((uncle == NULL) || (uncle != NULL && uncle->_color == BLACK)){//情况3:cur为红,p为红,g为黑,u不存在/u为黑(cur为parent的右孩子)//情况2:cur为红,p为红,g为黑,u不存在/u为黑(cur为parent的左孩子)if (parent->_right == cur){RotateL(parent);swap(cur,parent);}parent->_color = BLACK;grandfather->_color = RED;RotateR(grandfather);break;}}else // parent == grandfather->_right{Node* uncle = grandfather->_left;if (uncle && uncle->_color == RED)//叔叔为左,且为红色{parent->_color = uncle->_color = BLACK;grandfather->_color = RED;cur = grandfather;parent = cur->_parent;}//叔叔不存在,存在且为黑色else if((uncle == NULL) || (uncle != NULL && uncle->_color == BLACK)){if (cur == parent->_left){RotateR(parent);swap(cur,parent);}parent->_color = BLACK;grandfather->_color = RED;RotateL(grandfather);break;}}}_root->_color = BLACK;//根节点始终是黑色return true;}void RotateL(Node* parent){Node* subR = parent->_right;Node* subRL = subR->_left;parent->_right = subRL;if(subRL){subRL->_parent = parent;}Node* ppNode = parent->_parent;subR->_left = parent;parent->_parent = subR;if(ppNode == NULL){_root = subR;subR->_parent = NULL;}else{if(ppNode->_left == parent){ppNode->_left = subR;subR->_parent = ppNode;}else{ppNode->_right = subR;subR->_parent = ppNode;}}}void RotateR(Node* parent){Node* subL = parent->_left;Node* subLR = subL->_right;parent->_left = subLR;if(subLR){subLR->_parent = parent;}Node* ppNode = parent->_parent;subL->_right = parent;parent->_parent = subL;if(ppNode ==  NULL){_root = subL;subL->_parent = NULL;}else{if(ppNode->_left == parent){ppNode->_left = subL;}else{ppNode->_right = subL;}subL->_parent = ppNode;}}void InOrder(){return _InOrder(_root);cout<<endl;}bool IsBlance(){//1.检查根节点是否为黑色节点//2.检查每条路径上黑色节点的个数是否相等//3.检查是否有连续的红色节点int BlackCount = 0;Node* cur = _root;while(cur){if(cur->_color == BLACK){BlackCount++;}cur = cur->_left;}int curBlackCount = 0;return _IsBlance(_root,BlackCount,curBlackCount);}Node* Find(const K& key){return _Find(_root,key);}bool Remove(const K& key){}protected:Node* _Find(Node* root,const K& key){if(_root == NULL){return NULL;}while(root){if(root->_key == key){cout<<"Find"<<root->_key<<":"<<root->_value<<endl;return root;}else if(root->_key > key)root = root->_left;elseroot = root->_right;}cout<<"没有找到该节点"<<endl;return NULL;}bool _IsBlance(Node* root,int BlackCount,int curBlackCount){if(root == NULL){return true;}//1.检查根节点是否黑色节点if(_root->_color == RED){return false;}//3.是否有连续的红色节点if(root->_color == BLACK){curBlackCount++;}else{if(root->_parent && root->_parent->_color == RED){cout<<"有连续的红色节点:"<<root->_key<<endl;return false;}}//2.检查每条路径上黑色节点的个数if(root->_left == NULL && root->_right == NULL){if(BlackCount == curBlackCount){return true;}else{cout<<"黑色节点数量不相等"<<root->_key<<endl;return false;}}return _IsBlance(root->_left,BlackCount,curBlackCount)&& _IsBlance(root->_right,BlackCount,curBlackCount);}void _InOrder(Node* root){if(root == NULL){return;}_InOrder(root->_left);cout<<root->_key<<" ";_InOrder(root->_right);}protected:Node* _root;};void TestTree(){RBTree<int ,int> tree;int array[]={16, 3, 7, 11, 9, 26, 18, 14, 15};for(size_t i = 0; i < sizeof(array)/sizeof(array[0]); ++i){tree.Insert(array[i],i);}tree.InOrder();cout<<endl;cout<<"IsBlance?"<<tree.IsBlance()<<endl;;tree.Find(18);tree.Find(13);}

插入的5种情形:

情形1:该树为空树,直接插入根结点的位置,违反性质1,把节点颜色由红改为黑即可。

 
情形2:插入节点N的父节点P为黑色,不违反任何性质,无需做任何修改。
 
情形3:cur为红,p为红,g为黑,u存在且为红
操作:则将p,u改为黑,g改为红,然后把g当成cur,继续向上调整。

情形4:cur为红,p为红,g为黑,u不存在/u为黑
操作:p为g的左孩子,cur为p的左孩子,则进行右单旋转;相反,p为g的右孩子,cur为p的右孩子,则进行左单旋转
p、g变色--p变黑,g变红

情形5:cur为红,p为红,g为黑,u不存在/u为黑
操作:p为g的左孩子,cur为p的右孩子,则针对p做左单旋转;相反,p为g的右孩子,cur为p的左孩子,则针对p做右单旋转
则转换成了情况4
0 0
原创粉丝点击