红黑树基本操作实现

xiaoxiao2021-02-27  341

红黑树的插入,删除简单实现

主要理解的难点在删除的实现,当删除节点存在左右子节点时,需选择右侧后续节点,然后替换两个节点,当被替换节点是叶节点时,需要重新平衡该树,此时以空节点染黑代替进行平衡操作,再做各种变换,与书上的图操作相似, 详见“[balance]”

#ifndef CRBTREE_H #define CRBTREE_H #include <cstddef> using namespace std; enum NodeColor{ colorred, colorblack }; template <class T> struct RBNode { NodeColor color; RBNode *leftnode; RBNode *rightnode; RBNode *parentnode; T obj; }; template <class T> RBNode<T> *__InitNode(const T& obj) { RBNode<T> *rbnode = new RBNode<T>(); rbnode->color = colorred; rbnode->leftnode = NULL; rbnode->rightnode = NULL; rbnode->parentnode = NULL; rbnode->obj = obj; return rbnode; } template <class T> class CRBTree { public: typedef RBNode<T> NodeType; typedef NodeType* NodeTypePtr; typedef T value_type; CRBTree(){ headnode = NULL; } ~CRBTree(){ } bool Empty() { return headnode == NULL; } void Insert(const value_type &obj) { NodeType *newnode = __InitNode(obj); if (Empty()) { newnode->color = colorblack; headnode = newnode; } else { _InsertNode(newnode); if (newnode->parentnode->color == colorred) { _Recolor(newnode); } } } void Erase(const value_type &obj) { NodeType *_EraseNode = _FindNode(headnode, obj); if (_EraseNode) { NodeTypePtr _Fixnode; // the node to recolor as needed NodeTypePtr _Fixnodeparent; // parent of _Fixnode (which may be nil) NodeTypePtr _Pnode = _EraseNode; if (_Pnode->leftnode == NULL) _Fixnode = _Pnode->rightnode; // stitch up right subtree else if (_Pnode->rightnode == NULL) _Fixnode = _Pnode->leftnode; // stitch up left subtree else { // two subtrees, must lift successor node to replace erased _Pnode = (++iter(_EraseNode)).data(); // _Pnode is successor node _Fixnode = _Pnode->rightnode; // _Fixnode is only subtree } if (_Pnode == _EraseNode) { // at most one subtree, relink it,only black parent link one red child _Fixnodeparent = _EraseNode->parentnode; if (_Fixnode != NULL) _Fixnode->parentnode = _Fixnodeparent; if (headnode == _EraseNode) headnode = _Fixnode; else if (_Fixnodeparent->leftnode == _EraseNode) _Fixnodeparent->leftnode = _Fixnode; else _Fixnodeparent->rightnode = _Fixnode; } else { //two subtrees, find the successor node and swap with the Erasenode _EraseNode->leftnode->parentnode = _Pnode; _Pnode->leftnode = _EraseNode->leftnode; if (_EraseNode->rightnode == _Pnode) { _Fixnodeparent = _Pnode; } else { _Fixnodeparent = _Pnode->parentnode; if (_Fixnode != NULL) _Fixnode->parentnode = _Fixnodeparent; _Fixnodeparent->leftnode = _Fixnode; _Pnode->rightnode = _EraseNode->rightnode; _EraseNode->rightnode->parentnode = _Pnode; } if (headnode == _EraseNode) headnode = _Pnode; else if (_EraseNode->parentnode->leftnode == _EraseNode) _EraseNode->parentnode->leftnode = _Pnode; else _EraseNode->parentnode->rightnode = _Pnode; _Pnode->parentnode = _EraseNode->parentnode; //swap color NodeColor color = _Pnode->color; _Pnode->color = _EraseNode->color; _EraseNode->color = color; } if (_EraseNode->color == colorblack) { if (_Fixnode != NULL) _Fixnode->color = colorblack; else { //[balance] while (_Fixnode != headnode && (_Fixnode == NULL || _Fixnode->color == colorblack)) { if (_Fixnode == _Fixnodeparent->leftnode) { NodeTypePtr _Unclenode = _Fixnodeparent->rightnode; if (_Unclenode->color == colorred) { _Unclenode->color = colorblack; _Fixnodeparent->color = colorred; _LeftRotate(_Fixnodeparent); _Unclenode = _Fixnodeparent->rightnode; } if ((_Unclenode->leftnode == NULL || _Unclenode->leftnode->color == colorblack) && (_Unclenode->rightnode == NULL || _Unclenode->rightnode->color == colorblack)) { _Unclenode->color = colorred; _Fixnode = _Fixnodeparent; _Fixnodeparent = _Fixnodeparent->parentnode; } else { if (_Unclenode->rightnode == 0 || _Unclenode->rightnode->color == colorblack) { if (_Unclenode->leftnode != NULL) _Unclenode->leftnode->color = colorblack; _Unclenode->color = colorred; _RightRotate(_Unclenode); _Unclenode = _Fixnodeparent->rightnode; } _Unclenode->color = _Fixnodeparent->color; _Fixnodeparent->color = colorblack; if (_Unclenode->rightnode != NULL) _Unclenode->rightnode->color = colorblack; _LeftRotate(_Fixnodeparent); break; } } else { NodeTypePtr _UncleNode = _Fixnodeparent->leftnode; if (_UncleNode->color == colorred) { _UncleNode->color = colorblack; _Fixnodeparent->color = colorred; _RightRotate(_Fixnodeparent); _UncleNode = _Fixnodeparent->leftnode; } if ((_UncleNode->rightnode == NULL ||_UncleNode->rightnode->color == colorblack) && (_UncleNode->leftnode == NULL || _UncleNode->leftnode->color == colorblack)) { _UncleNode->color = colorred; _Fixnode = _Fixnodeparent; _Fixnodeparent = _Fixnodeparent->parentnode; } else { if (_UncleNode->leftnode == NULL || _UncleNode->leftnode->color == colorblack) { if (_UncleNode->rightnode) _UncleNode->rightnode->color = colorblack; _UncleNode->color = colorred; _LeftRotate(_UncleNode); _UncleNode = _Fixnodeparent->leftnode; } _UncleNode->color = _Fixnodeparent->color; _Fixnodeparent->color = colorblack; if (_UncleNode->leftnode) _UncleNode->leftnode->color = colorblack; _RightRotate(_Fixnodeparent); break; } } } if (_Fixnode) _Fixnode->color = colorblack; } } delete _EraseNode; } } class iter{ public: iter(NodeType *node) :_node(node) { } iter operator ++() { if (_node->rightnode) { _node = _node->rightnode; while(_node && _node->leftnode) { _node = _node->leftnode; } } else if (_node->parentnode == NULL) { _node = NULL; } else if (_node == _node->parentnode->leftnode) { _node = _node->parentnode; } else if (_node == _node->parentnode->rightnode) { NodeType *_parent = _node->parentnode; if (_parent->parentnode && _parent == _parent->parentnode->leftnode) { _node = _parent->parentnode; } else { _node = NULL; } } return *this; } bool operator == (const iter& other) { return _node == other._node; } bool operator != (const iter& other) { return _node != other._node; } NodeType* operator -> () const { return _node;} NodeType* data() const { return _node; } private: NodeType *_node; }; iter begin() { NodeType *_tnode = headnode; if (_tnode != NULL) { while(_tnode->leftnode) { _tnode = _tnode->leftnode; } } return iter(_tnode); } iter end() { return iter(NULL); } void clear() { _Erase(headnode); headnode = NULL; } private: NodeType *headnode; void _LeftRotate(NodeType *nodeA){ NodeType *nodeB = nodeA->rightnode; NodeType *nodeC = nodeB->leftnode; nodeA->rightnode = nodeC; if (nodeC) nodeC->parentnode = nodeA; nodeB->leftnode = nodeA; nodeB->parentnode = nodeA->parentnode; if (nodeA->parentnode == NULL) headnode = nodeB; else { if (nodeA->parentnode->leftnode == nodeA) nodeA->parentnode->leftnode = nodeB; else nodeA->parentnode->rightnode = nodeB; } nodeA->parentnode = nodeB; } void _RightRotate(NodeType *nodeA){ NodeType *nodeB = nodeA->leftnode; NodeType *nodeC = nodeB->rightnode; nodeA->leftnode = nodeC; if (nodeC) nodeC->parentnode = nodeA; nodeB->rightnode = nodeA; nodeB->parentnode = nodeA->parentnode; if (nodeA->parentnode == NULL) headnode = nodeB; else { if (nodeA->parentnode->leftnode == nodeA) nodeA->parentnode->leftnode = nodeB; else nodeA->parentnode->rightnode = nodeB; } nodeA->parentnode = nodeB; } void _InsertNode(NodeType *node) { NodeType *parent = headnode; do{ if (node->obj < parent->obj) { if (parent->leftnode == NULL) { parent->leftnode = node; node->parentnode = parent; break; } else parent = parent->leftnode; } else { if (parent->rightnode == NULL) { parent->rightnode = node; node->parentnode = parent; break; } else parent = parent->rightnode; } }while(1); } NodeType* _FindNode(NodeType *pNode,const value_type& obj) { NodeType *_node = pNode; do{ if (_node == NULL || _node->obj == obj) { return _node; } else if (_node->obj < obj) { return _FindNode(_node->rightnode, obj); } else { return _FindNode(_node->leftnode, obj); } }while(1); } void _Recolor(NodeType *node) { NodeType *_parent = node->parentnode; if (node == headnode) { node->color = colorblack; } else if (_parent->color == colorblack) { return; } else { NodeType *_grand = _parent->parentnode; if (_parent == _grand->leftnode) { NodeType *_uncle = _grand->rightnode; if (_uncle && _uncle->color == colorred) { _parent->color = colorblack; _uncle->color = colorblack; _grand->color = colorred; _Recolor(_grand); } else { if (node == _parent->rightnode) { node = node->parentnode; _LeftRotate(node); } node->parentnode->color = colorblack; node->parentnode->parentnode->color = colorred; _RightRotate(node->parentnode->parentnode); } } else { NodeType *_uncle = _grand->leftnode; if (_uncle && _uncle->color == colorred) { _parent->color = colorblack; _uncle->color = colorblack; _grand->color = colorred; _Recolor(_grand); } else { if (node == _parent->leftnode) { node = node->parentnode; _RightRotate(node); } node->parentnode->color = colorblack; node->parentnode->parentnode->color = colorred; _LeftRotate(node->parentnode->parentnode); } } } } void _Erase(NodeType *node) { for (NodeType *_Pnode = node; _Pnode != NULL; node = _Pnode) { // free subtrees, then node _Erase(_Pnode->rightnode); _Pnode = _Pnode->leftnode; delete node; } } }; #endif // CRBTREE_H

测试代码:

#include <iostream> #include "rbtree.h" using namespace std; void printtree(CRBTree<int>& rbtree) { //check tree balance int blackdepth = 0; for ( CRBTree<int>::iter it = rbtree.begin(); it != rbtree.end(); ++it) { int branchdepth = 0; if (it->leftnode == NULL || it->rightnode == NULL) { branchdepth ++; RBNode<int>* node = it.data(); while (node != NULL) { if (node->color == colorblack) branchdepth++; node = node->parentnode; } if (blackdepth == 0) blackdepth = branchdepth; else if (blackdepth != branchdepth) cout << "RBTree is not balance now!\n"; } } for ( CRBTree<int>::iter it = rbtree.begin(); it != rbtree.end(); ++it) { cout << it->obj; const char *temp = (it->color==colorblack) ? "B" : "R"; cout << temp; if (it->leftnode != NULL) cout << 'l'; if (it->rightnode != NULL) cout << 'r'; if (it->parentnode == NULL) cout << 'H'; cout << " "; } cout << endl; } int main() { CRBTree<int> rbtree; for (int i=0; i<61; i++) { rbtree.Insert(i); printtree(rbtree); } int arrint[] = {1, 7, 5, 20, 4, 6, 9, 10, 17, 3, 2, 15, 60, 55}; for (unsigned int i=sizeof(arrint)/sizeof(arrint[0]); i>0; i--) { rbtree.Erase(arrint[i-1]); printtree(rbtree); } rbtree.clear(); return 0; }

转载请注明原文地址: https://www.6miu.com/read-4900.html

最新回复(0)