Uploaded by siriuskoan.cs10

110550027

advertisement
Algorithm - HW2
110550027 管培勛
Runtime / Environment
The code is written in C++, compiling by g++ (version is g++ (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0 ), and runs on
my Ubuntu 20.04 VM
No IDE is used, I only use vim to write and use g++ command to compile
Results
I use struct to construct a node, and it contains its value ( val ), color ( color ), left ( L ) and right ( R ) children
and parent ( parent ).
We discuss insertion and deletion separately.
RB-Tree has some rules
1. root is black
2. node->color == red → node->L->color == black && node->R->color == black (when children exist), but the
reverse way does not hold
3. when the children do not exist, we regard it as black
4. any path from root to leaf (or empty leaf) has the same number of black nodes, we denote it as β
Insertion
We first create a node and add it to the tree.
A new node is colored red by default.
Recall that in BST, we go through the tree and find a proper place for the new node, and then we insert it.
However, normal BST do not store parent , but RB-Tree does, so we have to update new_node->parent , new_node>parent->L or new_node->parent->R (depends on the path it goes down).
Next, we need to do balance .
We explain the balance function, we only consider the subtree containing grand = new_node->parent->parent ,
parent = new_node->parent , uncle is the other node beside parent
1. when the new node do not have parent, it means that it is root , so we assign it to root and change its color
to black
2. when parent is black, we need not do anything since the new node which is red will not violate any rule (red
node does affect β)
3. when parent is red
1. when parent and uncle are both red (imply grand is black), then we can exchange the colors of them, i.e.,
parent->color = uncle->color = black and grand->color = red
Since we just exchange the colors of two layers, β will not change, and rule 2 is also solved
2. when parent is red but uncle is black (black or empty), we discuss four (2 × 2) cases (but only explain the
first since the others are similar)
1. grand->L->L == new_node
We know that grand is common for parent and uncle , so the color does not matter in this subtree.
Now, a new node which is red connects to a red node parent , it violates rule 2, so we have to make
parent black, and to maintain β, grand should be red
Here, we find that the uncle subtree has one fewer black nodes count since grand is recolored to red,
but parent subtree still has the same black nodes count, so we make a right_rotate to the parent node
However, we cannot make sure whether the whole tree is balanced, so we do balance again.
2. grand->R->R == new_node
3. grand->L->R == new_node
4. grand->R->L == new_node
Deletion
Recall that in BST deletion, we have three cases to discuss
1. remove leaf, just remove it and nothing more to do
2. remove a node with one children, move its children up ( parent->child = node->child )
3. remove a node with two children (the most complicated case), find the max in left subtree LR (or min in right
subtree, but the visualization tool does not use this and it produce different results, so I choose to use its way
and I can debug with the tool) and replace the current node with it, and finally remove LR
We have similar discussion in RB-Tree
1. when removing a node with two children
We find the left max LR , and replace node with LR
Next, we turn to removing LR , then the problem becomes removing a leaf, so we can continue
2. when removing a node with one children
We have four cases for (node, child) : (R,B),(R,R),(B,B),(B,R) , and we can find that only (B,R) is possible,
the reason is:
If the child is black, then rule 4 is violated, and (R,R) is impossible by rule 2
So in (B,R) case, we have to change the child to black to take the position of node
3. when removing a leaf
1. if the leaf is red, then just remove it, no rule will be violated
2. if the leaf is black, we need to discuss since it may affect β. We extract this part of code to another function
del_balance
We have two cases: node == parent->L and node == parent->R , and they have symmetry, so we only explain
the first one
We let sibling be the node beside node , and L = sibling->L , R = sibling->R
1. sibling->color == red , we have to do rotation for parent since when node is deleted, rule 4 will be
violated. So sibling will take the position of parent , and we need to parent->color = red and sibling>color = black (exchange colors)
2. sibling (from above else if ), sibling->R and sibling->L are all black (or empty), since the removal
of node will decrease the number of black nodes, so sibling has to be colored red
Then we consider when parent->color == red , we can maintain β by change it to black, and the balance
is done
Otherwise, we cannot do anything and have to do balance again (do not break ) starting at parent
3. The case is sibling->color == R->color == black and L->color == red
We make L which is red up, and keep balancing
4. when sibling->color == black and R->color == red . Since node is black and should be deleted, we
need a node to take on its position, so we need to do left_rotation to parent , and make parent black
And now sibling is new parent, it should have the color parent originally have
Also, R left on right subtree after rotation, so it must be black to avoid violating rule 4
By doing so, the rules are all met, so we can stop balancing
References
It is so hard to complete it only by my own, so I list some references
1. JavaScript 學演算法(十八)- 紅黑樹(下):刪除操作 – 竹白記事本 (chupai.github.io)
2. 1.4.3 Red-Black Tree - 資料結構&演算法筆記 (gitbook.io)
3. Red Black Tree: Delete(刪除資料)與Fixup(修正) (alrightchiu.github.io)
4. Red/Black Tree Visualization (usfca.edu)
5. My DS/OOP homework about BST and AVL
6. textbook
Download