Algorithm: 红黑树
2016-07-14 00:00
399 查看
摘要: 逐步完善
红黑树
一棵红黑树是满足下面性质的二叉搜索树:
1,每个结点或是红色,或是黑色的.
2,根节点必须是黑色的.
3,每个分支的最后一个结点是黑色.
4,如果一个结点是红色的,则它的两个子结点必然都是黑色.
5,对每个结点,从该结点到其所有后代叶结点的简单路径上,均包含相同数目的黑色结点.
红黑树
一棵红黑树是满足下面性质的二叉搜索树:
1,每个结点或是红色,或是黑色的.
2,根节点必须是黑色的.
3,每个分支的最后一个结点是黑色.
4,如果一个结点是红色的,则它的两个子结点必然都是黑色.
5,对每个结点,从该结点到其所有后代叶结点的简单路径上,均包含相同数目的黑色结点.
#include <iostream> #include <memory> #include <type_traits> //注明:以nullptr表示树的尾部. enum class Color : int{ Red, Black }; template<typename T> class Node{ public: T data; Color color; Node<T>* left; Node<T>* right; Node<T>* parent; public: Node(Color clir = Color::Black):color(clr),parent(nullptr),left(nullptr),right(nullptr){} template<typename Ty> Node(const Ty& dt, Color clr = Color::Black, Node<T>* lh=nullptr, Node<T>* rh=nullptr, Node<T>* pr=nullptr); Node(const T& dt, Color clr=Color::Black, Node<T>* lh=nullptr, Node<T>* rh=nullptr, Node<T>* pr=nullptr); ~Node()=default; }; template<typename T> template<typename Ty> Node<T>::Node(const Ty& dt, Color clr, Node<T>* lh, Node<T>* rh, Node<T>* pr) :data(dt), color(clr), left(lh), right(rh), parent(pr) { // } template<typename T> Node<T>::Node(const T& dt, Color clr, Node<T>* lh, Node<T>* rh, Node<T>* pr) :data(dt), color(clr), left(lh), right(rh), parent(pr) { // } template<typename T> class RBTree{ private: Node<T>* root; void leftRotate(Node<T>* rt, Node<T>* x); //在结点x上做左旋. void rightRotate(Node<T>* rt, Node<T>* y); //右旋在结点y上做右旋. void insertFixUp(Node<T>* rt, Node<T>* z); //插入修正保持红黑树的特性. void transPlant(Node<T>* first, Node<T>* second); //辅助删除结点. void deleteNode(Node<T>* node); //删除一个结点. Node<T>* minmumSubNode(Node<T>* node); //返回node中最小的子结点. void deleteFixUp(Node<T>* node); //删除修正,在删除一个红黑树结点后对红黑树进行修正保证红黑树的性质. //----------辅助函数----------- inline Node<T>* getParent(Node<T>* node) //获得一个函数的父结点. { return node->parent; } inline Node<T>* getGParent(Node<T>* node); //获得一个函数的父结点的父结点. { return (node->parent)->parent; } public: template<typename ...Args> RBTree(Args&&... parameters); RBTree(); ~RBTree(); }; //左旋: template<typename T> void RBTree<T>::leftRotate(Node<T>* rt, Node<T>* x) { Node<T>* y = x->right; x->right = y->left; if(y->left != nullptr){ y->left->parent = x; } y->parent = x->parent; if(y->parent == nullptr){ rt = y; }else if(x == x->parent->left){ x->parent->left = y; }else{ x->parent->right = y; } y->left = x; x->parent = y; } // 7 7 // / \ / \ // 4 11(x) 4 18(y) // / \ / \ leftRotate(x) / / \ // 3 6 9 18(y) ---------------> 3 11(x) 19 // / / \ <--------------- / / \ \ // 2 14 19 rightRotate(y) 2 9 14 22 // / \ \ / \ / // 12 17 22 12 17 20 // / // 20 //右旋: template<typename T> void RBTree<T>::rightRotate(Node<T>* rt, Node<T>* y) { Node<T>* x = y->left; y->left = x->right; if(x->right != nullptr){ x->right->parent = y; } x->parent = y->parent; if(y->parent == nullptr){ rt = x; }else if(y == y->parent->left){ y->parent->left = y; }else{ y->parent->left = x; } x->right = y; y->parent = x; } //插入修正. template<typename T> void RBTree<T>::insertFixUp(Node<T>* rt, Node<T>* z) { Node<T>* zParent = (this->getParent)(z); Node<T>* zGParent = (this->getGParent)(z); while(zParent->color == Color::Red){ if(zParent == zGParent->left){ Node<T>* y = zGParent->right; if(y->color == Color::Red){ zParent->color = Color::Black; y->color = Color::Black; zGParent->color = Color::Red; z = zGParent; zParent = (this->getParent)(z); zGParent = (this->getGParent)(z); }else if(z == zParent->right){ z = (this->getParent)(z); this->leftRotate(rt, z); } (this->getParent)(z)->color = Color::Black; (this->getGParent)(z)->color = Color::Red; this->rightRotate(rt, this->getGParent(z)); }else if(zParent == zGParent->right){ Node<T>* y = zGParent->left; if(y->color == Color::Red){ zParent->color = Color::Black; y->color = Color::Blac; zGParent->color = Color::Red; z = zGParent; zParent = (this->getParent)(z); zGParent = (this->getGParent)(z); }else if(z == zParent->left){ z = (this->getParent)(z); this->rightRotate(rt, z); } (this->getParent)(z)->color = Color::Black; (this->getGParent)(z)->color = Color::Red; this->rightRotate(rt, this->getGParent(z)); } } rt->color = Color::Black; } //辅助删除结点. 借鉴了二叉搜索树的transPlant. //1, 如果first结点是树根,那么就更新红黑树的根结点为. //2, 如果first为其父结点的左结点的情况. //3, 如果fist为其父亲右结点的情况. template<typename T> void RBTree<T>::transPlant(Node<T>* first, Node<T>* second) { if(first->parent == nullptr){ this->root = first; }else if(first == first->parent->left){ first->parent->left = second; }else{ first->parent->right = second; } first->parent = second->parent; } //辅助删除结点. 借鉴了二叉搜索树的minmum. //主要作用是把被删除的结点的2个子结点连接到被删除结点的父结点下面. template<typename T> Node<T>* RBTree<T>::minimumSubNode(Node<T>* node) { Node<T> tempNode = nullptr; if(node != nullptr){ while(node->left != nullptr){ tempNode = node->left; } } return tempNode; } //删除一个结点. template<typename T> void RBTree<T>::deleteNode(Node<T>* node) { Node<T>* tempNodeOne = node; Node<T>* tempNodeTwo = nullptr; Color tempColor = tempNode->color; if(node->left == nullptr){ tempNodeTwo = node->right; this->transPlant(node, node->right); }else if(node->right == nullptr){ tempNodeTwo = node->left; this->transPlant(node, node->left); }else{ tempNodeOne = minimumSubNode(node->right); tempColor = tempNodeOne->color; tempNodeTwo = tempNodeOne->right; if(tempNodeOne->parent == node){ tempNodeTwo->parent = tempNodeOne; }else{ this->transPlant(tempNodeOne, tempNodeOne->right); tempNodeOne->right = node->right; tempNodeOne->right->parent = tempNodeOne; } this->transPlant(node, tempNodeOne); tempNodeOne->left = node->left; tempNodeOne->left->parent = tempNodeOne; tempNodeOne->color = node->color; } if(tempColor == Color::Black){ } } //用于在删除一个结点过后修正红黑树的性质. template<typename T> void RBTree<T>::deleteFixUp(Node<T>* node) { Node<T>* tempNodeOne = nullptr; while(x != this->root && node->color == Color::Black){ if(node == node->parent->left){ tempNodeOne = node->parent->right; //case 1: if(tempNodeOne->color == Color::Red){ tempNodeOne->color = Black; this->leftRotate(this->root, node->parent);// notice! left-rotate! tempNodeOne = node->parent->right; } //case 2: if(tempNodeOne->left->color == Color::Black && tempNodeOne->right->color == Black){ tempNodeOne->color = Color::Red; node = node->parent; //case 3: }else if(tempNodeOne->right->color == Color::Black){ tempNodeOne->left->color = Color::Black; tempNodeOne->color = Color::Red; this->rightRotate(this->root, tempNodeOne); tempNodeOne = node->parent->right; } }else{ tempNodeOne = node->parent->left; } } }
相关文章推荐
- [django]django打印debug日志
- django小结
- google笔试题country leader
- Django用户认证系统
- nyist_30 Gone Fishing
- mongoose 创建自增字段方法
- Ubuntu 16.04下安装sogou 拼音输入法的错误问题
- i'm trying to [ip forward ] but even this is a no go
- ubuntu---sogou输入法设置
- 编写Django自定义manage命令
- Pokemon GO对AR行业有什么刺激
- nyoj 30 gone fishing
- 101 Hack 39 B Goodland Electricity locked (线段上的最少点覆盖 贪心)
- 在leangoo 里怎么设置工作量估算,添加附件,设置截止时间?
- Django通用视图讲解
- Windows下安装pip及django的restframework
- google protobuf详解
- POJ 3107 Godfather
- golang中的单元测试
- 关于AlphaGo和机器人云的一些想法