看演算法導論看的有點暈,代碼的縮排讓我直接抓狂了,網上找了一個比較靠譜的解法,連結
現在具體分析一下插入操作:
1. 首先父親節點如果是黑色節點的話,不需要處理了,多一個紅色節點不會有任何影響.
2. 如果父親節點是紅色的,而叔父節點也是紅色,那就是把父親和叔父節點同時改成黑色,祖父改為紅色,然後遞迴的向上傳遞.
3. 如果父親節點是紅色的,而叔父節點是黑色的. 後面的話比較拗口.父親是祖父的左孩子.
(1)如果自己是父親的左
孩子,那麼修改父親為黑色,祖父為紅色,然後右轉祖父
(2)如果自己是父親的右
孩子,那麼先把自己指向父親,再做左轉自己,執行(1).
4. 如果父親是祖父的右孩子
(1)如果自己是父親的右
孩子,那麼修改父親為黑色,祖父為紅色,然後左轉祖父
(2)如果自己是父親的左
孩子,那麼先把自己指向父親,再做右轉自己,執行(1).
(以上轉自
上述網頁,並根據網頁中的代碼對描述作了適當的修改)。
對應的代碼如下:
template <class T><br />void RBTree<T>::RBInsert(RBTreeNode<T>*node)<br />{<br />RBTreeNode<T> *y = RBTreeNode<T>::NIL,<br />*x = root;<br />while (x!=RBTreeNode<T>::NIL)<br />{<br />y = x;<br />if(y->value == node->value)<br />return;<br />if(y->value >node->value)<br />x = x->left;<br />else x = x->right;<br />}<br />node->father = y;<br />if(y==RBTreeNode<T>::NIL)//node 為root<br />root = node;<br />else if(node->value < y->value)//left child<br />y->left = node;<br />else y->right = node;<br />node->left = node->right = RBTreeNode<T>::NIL;<br />node->color = RED;<br />RBInsertFixUp(node);<br />}<br />template<class T><br />void RBTree<T>::RBInsertFixUp(RBTreeNode<T>*node)<br />{<br />while (node!= root && node->father->color == RED)<br />{<br />RBTreeNode<T>* pUncle = GetUncle(node),<br />*pGrandFather = GetGrandFather(node);<br />if (pUncle!= RBTreeNode<T>::NIL && pUncle->color == RED)<br />{<br />node->father->color = BLACK;<br />pUncle->color = BLACK;<br />pGrandFather->color = RED;<br />node = pGrandFather;<br />}<br />else<br />{//if uncle = black<br />if (node->father == pGrandFather->left)<br />{//father is left child<br />if(node == node->father->right)<br />{//right child<br />node = node->father;<br />LeftRotate(node);<br />}<br />node->father->color = BLACK;<br />pGrandFather->color = RED;<br />RightRotate(pGrandFather);<br />}<br />else<br />{//father is right child<br />if(node == node->father->left)<br />{//left child<br />node = node->father;<br />RightRotate(node);<br />}<br />node->father->color = BLACK;<br />pGrandFather->color = RED;<br />LeftRotate(pGrandFather);<br />}<br />}<br />}<br />root->color = BLACK;<br />}
現在來看看紅/黑樹狀結構的刪除操作:
在這裡先暫且複習一下樹中節點x的後繼操作:
1. 如果x含有右子,則返回右子中的最小值(不停地遍曆右子的左枝)
2. 沒有右子,令x的父節點為y,如果x是y的左子,則直接返回y
3. x是y的右子,則迭代{x = y;y=y->father;}直到y為空白或者x是y的右子為止。
代碼如下:
template<class T><br />const TreeNode<T>* Tree<T>::TreeSuccessor(const TreeNode<T> * const node)<br />{<br />if(!node)<br />return NULL;<br />if (node->right)<br />{<br /> TreeNode<T>* minNode = node;<br /> while(minNode ->left)<br /> minNode = minNode->left;<br /> return minNode;<br /> }<br />TreeNode<T>* temp = node->father;<br />const TreeNode<T>*tempf = node;<br />while(temp && tempf == temp->right)<br />{<br />tempf = temp;<br />temp = temp->father;<br />}<br />return temp;<br />}
另外簡單證明一下二叉樹節點node的後繼無左子的定理:
反證法:
假設node的後繼successor有左子left:
1. 如果node.value<left.value
則node的後繼為left而非successor
2. 如果node.value>left.value
則left不可能為successor的左子樹(因為如果left的value比node要小,則left必在node的左子樹中,而node的後繼一定大於node,一定不在node的左子樹中)
矛盾。因此定理成立。
現在分析一下紅/黑樹狀結構的刪除操作,以下為了表示簡便,F代表父節點,S代表兄弟節點,x表示當前節點:
1. 如果x不為根並且x為黑色,執行2,否則執行6。
2. 如果x為右子,執行5,否則:
如果S為黑,執行3,否則:
置S為黑,F為紅,左旋F,並更新S為F的右子
3. 如果S的兩子均為黑,置S為紅,x更新為F,執行1;
否則執行4
4. 這裡分兩種情況:
4.1 如果S的右子為黑,S的左子也置黑,S置紅,S更新為F的右子,否則直接執行4.2
4.2 S的顏色置為F的顏色,F置黑,S右子置黑,左旋F,x更新為root,執行6
5. 和2-4對稱,只需要把left換為right即可
6. 置x為黑色(x為根或者x為紅色)
這個說起來還是很繞口,其實就是刪除一個紅節點不影響樹的紅黑性質,但是刪除樹的黑節點則會影響以下三點:
1 具有等同黑高的性質
2 如果刪除了x,而x的孩子和父親都為紅色,則違反了紅節點只能有黑孩子的性質
3 如果x只有一個紅孩子,則x為根,刪除了x會破壞根為黑色的性質。
根據以上的討論,需要檢查被刪除節點的孩子的情況。
所有的代碼如下:
#ifndef HIT_RB_TREE<br />#define HIT_RB_TREE<br />using std::cout;<br />using std::endl;<br />namespace HITRB_TREE<br />{<br />enum Color{BLACK = 0,RED};<br />//enum void{SUCCEED = 0,NOTFOUND,NULLNODE,DUPLICATENODE};<br />template<class T><br />struct RBTreeNode<br />{<br />T value;<br />RBTreeNode<T> *father;<br />RBTreeNode<T> *left;<br />RBTreeNode<T> *right;<br />Color color;</p><p>RBTreeNode():value(static_cast<T>(0)),father(NULL),left(NULL),right(NULL),<br />color(BLACK){}<br />RBTreeNode(T va,RBTreeNode<T> *f = NULL,RBTreeNode<T> *l = NULL,<br />RBTreeNode<T> *r=NULL,Color col=BLACK)<br />:value(va),father(f),left(l),right(r),color(col){}<br />};<br />template<class T><br />class RBTree<br />{<br />public:<br />RBTree()<br />{<br />pGuard = new RBTreeNode<T>;<br />pGuard->father = pGuard->left = pGuard->right = pGuard;<br />root = pGuard;<br />}<br />~RBTree()<br />{<br />DistroyTree(root);<br />delete pGuard;<br />pGuard = NULL;<br />}<br />void RBInsert(RBTreeNode<T>*node);<br />void RBInsert(const T &va);<br />void Remove(const T& va);<br />void Remove(RBTreeNode<T>*pNode);<br />RBTreeNode<T>* RBSearch(const T&);<br />void DistroyTree(RBTreeNode<T> *pNode);<br />const RBTreeNode<T>* Successor(const RBTreeNode<T>*node);<br />const RBTreeNode<T>* MaxNode(const RBTreeNode<T>*node);<br />const RBTreeNode<T>* const GetGuardNode()const{return pGuard;}<br />protected:<br />private:<br />void LeftRotate(RBTreeNode<T>*node);<br />void RightRotate(RBTreeNode<T>*node);<br />void RBInsertFixUp(RBTreeNode<T>*node);<br />void RBRemoveFixUp(RBTreeNode<T>*pNode);<br />RBTreeNode<T>* NewNode(const T &value)<br />{<br />RBTreeNode<T> *pNode =<br />new RBTreeNode<T>(value,pGuard,pGuard,pGuard);<br />return pNode;<br />}</p><p>RBTreeNode<T>* GetGrandFather(const RBTreeNode<T>*node)const<br />{<br />if(node!=pGuard && node->father!=pGuard)<br />return node->father->father;<br />else return pGuard;<br />}<br />RBTreeNode<T>* GetUncle(const RBTreeNode<T>*node)const<br />{<br />RBTreeNode<T>* pTemp = GetGrandFather(node);<br />if(pTemp == pGuard)<br />return pGuard;<br />if(node->father == pTemp->left)<br />return pTemp->right;<br />else return pTemp->left;<br />}<br />RBTreeNode<T>* GetSibling(const RBTreeNode<T>*node)const<br />{<br />if(node == node->father->left)<br />return node->father->right;<br />else return node->father->left;<br />}<br />RBTreeNode<T> *root;<br />RBTreeNode<T> *pGuard;<br />};<br />//function definition<br />template<class T><br />void RBTree<T>::DistroyTree(RBTreeNode<T> *pNode)<br />{<br />if(pNode != pGuard)<br />{<br />DistroyTree(pNode->left);<br />DistroyTree(pNode->right);<br />delete pNode;<br />pNode = NULL;<br />}<br />}<br />template<class T><br />void RBTree<T>::LeftRotate(RBTreeNode<T>*node)<br />{<br />if(node->right == pGuard)<br />{<br />cout<<"[WARNING +1000] node["<<node->value<<"] does not have any right node, cant be"<br /><<" left rotate!"<<endl;<br />return;<br />}<br />//y為node的右子<br />RBTreeNode<T> *y = node->right;<br />//把node的右子更新為其右子的左子<br />node->right = y->left;<br />//對更新的資料做處理,如果右子的左子不為空白,則把其父節點修正為node<br />if(y->left != pGuard)<br />y->left->father = node;<br />//把y的父節點更新為node的父節點<br />y->father = node->father;<br />//node為root的情況<br />if(node->father == pGuard)<br />root = y;<br />//把y連結到node的父節點的正確位置上(左子還是右子)<br />else if(node == node->father->left)<br />node->father->left = y;<br />else node->father->right = y;<br />//更新y和node的連結關係<br />y->left = node;<br />node->father = y;<br />}<br />template<class T><br />void RBTree<T>::RightRotate(RBTreeNode<T>*node)<br />{<br />if(node->left == pGuard)<br />{<br />cout<<"[WARNING +1000] node["<<node->value<<"] does not have any left node, cant be"<br /><<" right rotate!"<<endl;<br />return;<br />}<br />//y為node的左子<br />RBTreeNode<T> *y = node->left;<br />//把node的左子更新為其左子的右子<br />node->left = y->right;<br />//對更新的資料做處理,如果左子的右子不為空白,則把其父節點修正為node<br />if(y->right != pGuard)<br />y->right->father = node;<br />//把y的父節點更新為node的父節點<br />y->father = node->father;<br />//node為root的情況<br />if(node->father == pGuard)<br />root = y;<br />//把y連結到node的父節點的正確位置上(左子還是右子)<br />else if(node == node->father->left)<br />node->father->left = y;<br />else node->father->right = y;<br />//更新y和node的連結關係<br />y->right = node;<br />node->father = y;<br />}<br />template <class T><br />void RBTree<T>::RBInsert(RBTreeNode<T>*node)<br />{<br />RBTreeNode<T> *y = pGuard,<br />*x = root;<br />while (x!=pGuard)<br />{<br />y = x;<br />if(y->value == node->value)<br />return ;//DUPLICATENODE;<br />if(y->value >node->value)<br />x = x->left;<br />else x = x->right;<br />}<br />node->father = y;<br />if(y==pGuard)//node 為root<br />root = node;<br />else if(node->value < y->value)//left child<br />y->left = node;<br />else y->right = node;<br />node->left = node->right = pGuard;<br />node->color = RED;<br />RBInsertFixUp(node);<br />return;// SUCCEED;<br />}<br />template<class T><br />void RBTree<T>::RBInsertFixUp(RBTreeNode<T>*node)<br />{<br />while (node->father->color == RED)<br />{<br />RBTreeNode<T>* pUncle = GetUncle(node),<br />*pGrandFather = GetGrandFather(node);<br />if (pUncle->color == RED)<br />{<br />node->father->color = BLACK;<br />pUncle->color = BLACK;<br />pGrandFather->color = RED;<br />node = pGrandFather;<br />}<br />else<br />{//if uncle = black<br />if (node->father == pGrandFather->left)<br />{//father is left child<br />if(node == node->father->right)<br />{//right child<br />node = node->father;<br />LeftRotate(node);<br />}<br />node->father->color = BLACK;<br />pGrandFather->color = RED;<br />RightRotate(pGrandFather);<br />}<br />else<br />{//father is right child<br />if(node == node->father->left)<br />{//left child<br />node = node->father;<br />RightRotate(node);<br />}<br />node->father->color = BLACK;<br />pGrandFather->color = RED;<br />LeftRotate(pGrandFather);<br />}<br />}<br />}<br />root->color = BLACK;<br />}<br />template <class T><br />void RBTree<T>::RBInsert(const T&va)<br />{<br />RBInsert(NewNode(va));<br />return;// SUCCEED;<br />}<br />template<class T><br />const RBTreeNode<T>* RBTree<T>::Successor(const RBTreeNode<T>*node)<br />{//調用之間應該檢查node是否為MaxNode<br />if(node == pGuard)<br />return pGuard;<br />const RBTreeNode<T>*pTemp = node;<br />if (pTemp->right!=pGuard)<br />{//find the minim element in right sub-tree<br />while (pTemp->left!=pGuard)<br />{<br />pTemp = pTemp->left;<br />}<br />return pTemp;<br />}<br />RBTreeNode<T>*pTempFather = node->father;<br />while (pTempFather != pGuard &&<br />node == pTempFather->right)<br />{<br />pTemp = pTempFather;<br />pTempFather = pTempFather->father;<br />}<br />return pTempFather;<br />}<br />template<class T><br />const RBTreeNode<T>* RBTree<T>::MaxNode(const RBTreeNode<T>*node)<br />{<br />if(node == NULL)<br />node = root;<br />const RBTreeNode<T>*pTemp = node;<br />while (pTemp->right!=pGuard)<br />pTemp = pTemp->right;<br />return pTemp;<br />}<br />template<class T><br />void RBTree<T>::Remove(RBTreeNode<T>*pNode)<br />{<br />//null node<br />if(pNode == NULL || pNode == pGuard)<br />return;// NULLNODE;</p><p>//temp point definition<br />RBTreeNode<T> *pTemp=pGuard,<br />*pTempNode = pGuard;<br />if (pNode->left == pGuard ||<br />pNode->right == pGuard)<br />pTempNode = pNode;<br />else pTempNode = const_cast<RBTreeNode<T>*>( Successor(pNode) );<br />if(pTempNode->left != pGuard)<br />pTemp = pTempNode->left;//maybe NIL<br />else pTemp = pTempNode->right;//maybe successor's right node!<br />pTemp->father = pTempNode->father;//different form BST, need not check<br />if(pTempNode->father == pGuard)<br />root = pTemp;//set the root to NIL<br />else if(pTempNode == pTempNode->father->left)<br />pTempNode->father->left = pTemp;<br />else pTempNode->father->right = pTemp;<br />if(pNode != pTempNode)<br />{//has two children, and the pTempNode is pointing to successor.<br />//now need to copy the successor's data to node<br />pNode->color = pTempNode->color;<br />pNode->father = pTempNode->father;<br />pNode->left = pTempNode->left;<br />pNode->right = pTempNode->right;<br />pNode->value = pTempNode->value;<br />}</p><p>if(pTempNode->color == BLACK)//change the black height, so need to fix up!<br />RBRemoveFixUp(pTemp);<br />delete pTempNode;<br />pTempNode = NULL;<br />return;// SUCCEED;<br />}<br />template<class T><br />void RBTree<T>::RBRemoveFixUp(RBTreeNode<T>*pNode)<br />{<br />while (pNode != root && pNode->color == BLACK)<br />{<br />RBTreeNode<T> *pFather = pNode->father;<br />RBTreeNode<T> *pSibling = pFather->right;<br />if (pNode == pNode->father->left)<br />{<br />if (pSibling->color == RED)<br />{<br />pSibling->color = BLACK;<br />pFather->color = RED;<br />LeftRotate(pFather);<br />pSibling = pFather->right;<br />}<br />if (pSibling->left->color == BLACK &&<br />pSibling->right->color == BLACK)<br />{<br />pSibling->color = RED;<br />pNode = pFather;<br />}<br />else<br />{<br />if (pSibling->right->color == BLACK)//sibling's left is red<br />{<br />pSibling->left->color = BLACK;<br />pSibling->color = RED;<br />RightRotate(pSibling);<br />pSibling = pFather->right;<br />}<br />//right is red, left is unsure<br />pSibling->color = pFather->color;<br />pFather->color = BLACK;<br />pSibling->right->color = BLACK;<br />LeftRotate(pFather);<br />pNode = root;<br />}<br />}<br />else<br />{<br />if (pSibling->color == RED)<br />{<br />pSibling->color = BLACK;<br />pFather->color = RED;<br />RightRotate(pFather);<br />pSibling = pFather->left;<br />}<br />if (pSibling->left->color == BLACK &&<br />pSibling->right->color == BLACK)<br />{<br />pSibling->color = RED;<br />pNode = pFather;<br />}<br />else<br />{<br />if (pSibling->left->color == BLACK)//sibling's left is red<br />{<br />pSibling->right->color = BLACK;<br />pSibling->color = RED;<br />LeftRotate(pSibling);<br />pSibling = pFather->left;<br />}<br />//two children of sibling are both red<br />pSibling->color = pFather->color;<br />pFather->color = BLACK;<br />pSibling->left->color = BLACK;<br />RightRotate(pFather);<br />pNode = root;<br />}<br />}<br />}<br />pNode->color = BLACK;<br />}<br />template<class T><br />void RBTree<T>::Remove(const T& value)<br />{<br />//temp point definition<br />RBTreeNode<T> *pTemp=pGuard,<br />*pTempNode = pGuard,<br />*pNode = root;<br />//find the right position<br />RBSearch(value);<br />if(pNode == pGuard)<br />return;// NOTFOUND;<br />if (pNode->left == pGuard ||<br />pNode->right == pGuard)<br />pTempNode = pNode;<br />else pTempNode = const_cast<RBTreeNode<T>*>( Successor(pNode) );<br />if(pTempNode->left != pGuard)<br />pTemp = pTempNode->left;//maybe NIL<br />else pTemp = pTempNode->right;//maybe successor's right node!<br />pTemp->father = pTempNode->father;//different form BST, need not check<br />if(pTempNode->father == pGuard)<br />root = pTemp;//set the root to NIL<br />else if(pTempNode == pTempNode->father->left)<br />pTempNode->father->left = pTemp;<br />else pTempNode->father->right = pTemp;<br />if(pNode != pTempNode)<br />{//has two children, and the pTempNode is pointing to successor.<br />//now need to copy the successor's data to node<br />pNode->color = pTempNode->color;<br />pNode->father = pTempNode->father;<br />pNode->left = pTempNode->left;<br />pNode->right = pTempNode->right;<br />pNode->value = pTempNode->value;<br />}<br />if(pTempNode->color == BLACK)//change the black height, so need to fix up!<br />RBRemoveFixUp(pTemp);<br />delete pTempNode;<br />pTempNode = NULL;<br />return;// SUCCEED;<br />}<br />template<class T><br />RBTreeNode<T>* RBTree<T>::RBSearch(const T&value)<br />{<br />RBTreeNode<T> *pNode = root;<br />while (pNode!=pGuard)<br />{<br />if(pNode->value >value)<br />pNode = pNode->left;<br />else if (pNode->value < value)<br />pNode = pNode->right;<br />else if(pNode->value == value)<br />break;<br />}<br />return pNode;//maybe NIL<br />}<br />}//end of namespace<br />#endif