feat(tree): first attempt at wikipedia pseudo code
							parent
							
								
									1d458c68a4
								
							
						
					
					
						commit
						17c2e15385
					
				|  | @ -124,6 +124,22 @@ void vieter_tree_node_balance_after_insert(vieter_tree_node *node) { | |||
|   } | ||||
| } | ||||
| 
 | ||||
| vieter_tree_node *vieter_tree_node_rotate(vieter_tree_node *old_root, | ||||
|                                           bool dir) { | ||||
|   vieter_tree_node *new_root = old_root->children[1 - dir]; | ||||
| 
 | ||||
|   // Right rotation
 | ||||
|   if (dir) { | ||||
|     vieter_tree_node_set_child(old_root, new_root->children[1], false); | ||||
|     vieter_tree_node_set_child(new_root, old_root, true); | ||||
|   } else { | ||||
|     vieter_tree_node_set_child(old_root, new_root->children[0], true); | ||||
|     vieter_tree_node_set_child(new_root, old_root, false); | ||||
|   } | ||||
| 
 | ||||
|   return new_root; | ||||
| } | ||||
| 
 | ||||
| void vieter_tree_node_remove_balanced(vieter_tree_node *node) { | ||||
|   // A red node can only have 0 or 2 children. The node we receive only has
 | ||||
|   // one child at most, so we know if it's red that it doesn't have any
 | ||||
|  | @ -145,4 +161,80 @@ void vieter_tree_node_remove_balanced(vieter_tree_node *node) { | |||
|   } | ||||
| 
 | ||||
|   // The complicated case is when we want to remove a black leaf
 | ||||
|   // https://en.wikipedia.org/wiki/Red%E2%80%93black_tree#Removal_of_a_black_non-root_leaf
 | ||||
| 
 | ||||
|   vieter_tree_node *parent = node->parent; | ||||
|   vieter_tree_node *sibling, *close_nephew, *distant_nephew; | ||||
|   bool dir = vieter_tree_node_get(node, vieter_tree_node_right); | ||||
|   parent->children[dir] = NULL; | ||||
| 
 | ||||
|   vieter_tree_node_free(node); | ||||
| 
 | ||||
|   goto start; | ||||
| 
 | ||||
|   do { | ||||
|     dir = vieter_tree_node_get(node, vieter_tree_node_right); | ||||
| 
 | ||||
|   start: | ||||
|     sibling = parent->children[1 - dir]; | ||||
|     distant_nephew = sibling->children[1 - dir]; | ||||
|     close_nephew = sibling->children[dir]; | ||||
| 
 | ||||
|     if (!vieter_tree_node_get(sibling, vieter_tree_node_black)) | ||||
|       goto case3; | ||||
| 
 | ||||
|     if (distant_nephew != NULL && | ||||
|         !vieter_tree_node_get(distant_nephew, vieter_tree_node_black)) | ||||
|       goto case6; | ||||
| 
 | ||||
|     if (close_nephew != NULL && | ||||
|         !vieter_tree_node_get(close_nephew, vieter_tree_node_black)) | ||||
|       goto case5; | ||||
| 
 | ||||
|     if (!vieter_tree_node_get(parent, vieter_tree_node_black)) | ||||
|       goto case4; | ||||
| 
 | ||||
|     // Case 2
 | ||||
|     vieter_tree_node_set(sibling, vieter_tree_node_black, false); | ||||
|     node = parent; | ||||
|   } while ((parent = node->parent) != NULL); | ||||
| 
 | ||||
|   // Case 1
 | ||||
|   return; | ||||
| 
 | ||||
| case3: | ||||
|   vieter_tree_node_rotate(parent, dir); | ||||
|   vieter_tree_node_set(parent, vieter_tree_node_black, false); | ||||
|   vieter_tree_node_set(sibling, vieter_tree_node_black, true); | ||||
|   sibling = close_nephew; | ||||
|   distant_nephew = sibling->children[1 - dir]; | ||||
| 
 | ||||
|   if (distant_nephew != NULL && | ||||
|       !vieter_tree_node_get(distant_nephew, vieter_tree_node_black)) | ||||
|     goto case6; | ||||
| 
 | ||||
|   close_nephew = sibling->children[dir]; | ||||
| 
 | ||||
|   if (close_nephew != NULL && | ||||
|       !vieter_tree_node_get(close_nephew, vieter_tree_node_black)) | ||||
|     goto case5; | ||||
| 
 | ||||
| case4: | ||||
|   vieter_tree_node_set(sibling, vieter_tree_node_black, false); | ||||
|   vieter_tree_node_set(parent, vieter_tree_node_black, true); | ||||
|   return; | ||||
| 
 | ||||
| case5: | ||||
|   vieter_tree_node_rotate(sibling, 1 - dir); | ||||
|   vieter_tree_node_set(sibling, vieter_tree_node_black, false); | ||||
|   vieter_tree_node_set(close_nephew, vieter_tree_node_black, true); | ||||
|   distant_nephew = sibling; | ||||
|   sibling = close_nephew; | ||||
| 
 | ||||
| case6: | ||||
|   vieter_tree_node_rotate(parent, dir); | ||||
|   vieter_tree_node_set(sibling, vieter_tree_node_black, | ||||
|                        vieter_tree_node_get(parent, vieter_tree_node_black)); | ||||
|   vieter_tree_node_set(parent, vieter_tree_node_black, true); | ||||
|   vieter_tree_node_set(distant_nephew, vieter_tree_node_black, true); | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue