【数据结构】红黑树
发布时间:2020-12-15 05:49:50 所属栏目:安全 来源:网络整理
导读:红黑树是一棵二叉搜索树,它在每个节点上增加了一个存储位来表示节点的颜色,可以是Red或Black。通过对任何一条从根到叶子简单路径上的 颜色来约束,红黑树保证最长路径不超过最短路径的两倍,因而近似于平衡。 红黑树是满足下面红黑性质的二叉搜索树 每个节
红黑树是一棵二叉搜索树,它在每个节点上增加了一个存储位来表示节点的颜色,可以是Red或Black。通过对任何一条从根到叶子简单路径上的
颜色来约束,红黑树保证最长路径不超过最短路径的两倍,因而近似于平衡。
Test.cpp(主函数)
#include<iostream> using namespace std; #include"RBTree.h" int main() { TestTree(); getchar(); return 0; } RBTree.h(头文件) #pragma once enum 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; else root = 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,curBlackCount) && _IsBlance(root->_right,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 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |