feat(tree): first attempt at balanced inserts
							parent
							
								
									41bc6516fa
								
							
						
					
					
						commit
						1c591ac423
					
				|  | @ -1,3 +1,95 @@ | ||||||
| #include "balancing.h" | #include "balancing.h" | ||||||
| 
 | 
 | ||||||
| void vieter_tree_node_balance_after_insert(vieter_tree_node *node) {} | vieter_tree_node *vieter_tree_node_balance(vieter_tree_node *node) { | ||||||
|  |   vieter_tree_node *parent = node->parent; | ||||||
|  |   vieter_tree_node *grand_parent = parent->parent; | ||||||
|  |   vieter_tree_node *grand_grand_parent = grand_parent->parent; | ||||||
|  |   vieter_tree_node *root, *left, *right; | ||||||
|  |   vieter_tree_node *children[4]; | ||||||
|  | 
 | ||||||
|  |   if (node->key < parent->key && parent->key < grand_parent->key) { | ||||||
|  |     root = parent; | ||||||
|  |     left = node; | ||||||
|  |     right = grand_parent; | ||||||
|  | 
 | ||||||
|  |     children[0] = node->left; | ||||||
|  |     children[1] = node->right; | ||||||
|  |     children[2] = parent->right; | ||||||
|  |     children[3] = grand_parent->right; | ||||||
|  |   } else if (node->key < parent->key && parent->key > grand_parent->key) { | ||||||
|  |     root = node; | ||||||
|  |     left = grand_parent; | ||||||
|  |     right = parent; | ||||||
|  | 
 | ||||||
|  |     children[0] = grand_parent->left; | ||||||
|  |     children[1] = node->left; | ||||||
|  |     children[2] = node->right; | ||||||
|  |     children[3] = parent->right; | ||||||
|  |   } else if (node->key > parent->key && parent->key < grand_parent->key) { | ||||||
|  |     root = node; | ||||||
|  |     left = parent; | ||||||
|  |     right = grand_parent; | ||||||
|  | 
 | ||||||
|  |     children[0] = parent->left; | ||||||
|  |     children[1] = node->left; | ||||||
|  |     children[2] = node->right; | ||||||
|  |     children[3] = grand_parent->right; | ||||||
|  |   } else { | ||||||
|  |     root = parent; | ||||||
|  |     left = grand_parent; | ||||||
|  |     right = node; | ||||||
|  | 
 | ||||||
|  |     children[0] = grand_parent->left; | ||||||
|  |     children[1] = parent->left; | ||||||
|  |     children[2] = node->left; | ||||||
|  |     children[3] = node->right; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   vieter_tree_node_set(left, vieter_node_black); | ||||||
|  |   vieter_tree_node_set(right, vieter_node_black); | ||||||
|  |   vieter_tree_node_unset(root, vieter_node_black); | ||||||
|  | 
 | ||||||
|  |   left->left = children[0]; | ||||||
|  |   left->right = children[1]; | ||||||
|  | 
 | ||||||
|  |   if (children[0] != NULL) | ||||||
|  |     children[0]->parent = left; | ||||||
|  | 
 | ||||||
|  |   if (children[1] != NULL) | ||||||
|  |     children[1]->parent = left; | ||||||
|  | 
 | ||||||
|  |   right->left = children[2]; | ||||||
|  |   right->right = children[3]; | ||||||
|  | 
 | ||||||
|  |   if (children[2] != NULL) | ||||||
|  |     children[2]->parent = right; | ||||||
|  | 
 | ||||||
|  |   if (children[3] != NULL) | ||||||
|  |     children[3]->parent = right; | ||||||
|  | 
 | ||||||
|  |   root->left = left; | ||||||
|  |   root->right = right; | ||||||
|  |   left->parent = root; | ||||||
|  |   right->parent = root; | ||||||
|  | 
 | ||||||
|  |   if (grand_grand_parent != NULL) { | ||||||
|  |     vieter_tree_node_add_child(grand_grand_parent, root->key, root); | ||||||
|  |   } else { | ||||||
|  |     root->parent = NULL; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return root; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void vieter_tree_node_balance_after_insert(vieter_tree_node *node) { | ||||||
|  |   while (!vieter_tree_node_get(node, vieter_node_black) && | ||||||
|  |          node->parent != NULL && | ||||||
|  |          !vieter_tree_node_get(node->parent, vieter_node_black)) { | ||||||
|  |     node = vieter_tree_node_balance(node); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   // The root must always be black
 | ||||||
|  |   if (node->parent == NULL) { | ||||||
|  |     vieter_tree_node_set(node, vieter_node_black); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| #include "node.h" | #include "node.h" | ||||||
|  | #include "balancing.h" | ||||||
| 
 | 
 | ||||||
| vieter_tree_node *vieter_tree_node_init() { | vieter_tree_node *vieter_tree_node_init() { | ||||||
|   return calloc(1, sizeof(vieter_tree_node)); |   return calloc(1, sizeof(vieter_tree_node)); | ||||||
|  | @ -55,6 +56,7 @@ vieter_tree_error vieter_tree_node_insert(vieter_tree_node *root, uint64_t key, | ||||||
|   new_node->data = data; |   new_node->data = data; | ||||||
| 
 | 
 | ||||||
|   vieter_tree_node_add_child(parent, key, new_node); |   vieter_tree_node_add_child(parent, key, new_node); | ||||||
|  |   vieter_tree_node_balance_after_insert(new_node); | ||||||
| 
 | 
 | ||||||
|   return vieter_tree_ok; |   return vieter_tree_ok; | ||||||
| } | } | ||||||
|  | @ -95,20 +97,6 @@ vieter_tree_error vieter_tree_node_search(void **out, vieter_tree_node *root, | ||||||
|   return vieter_tree_ok; |   return vieter_tree_ok; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| vieter_tree_node *vieter_tree_node_successor(vieter_tree_node *node) { |  | ||||||
|   if ((node->left != NULL) ^ (node->right != NULL)) { |  | ||||||
|     return node->left != NULL ? node->left : node->right; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   node = node->right; |  | ||||||
| 
 |  | ||||||
|   while (node->left != NULL) { |  | ||||||
|     node = node->left; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   return node; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| vieter_tree_error vieter_tree_node_remove(void **out, vieter_tree_node *root, | vieter_tree_error vieter_tree_node_remove(void **out, vieter_tree_node *root, | ||||||
|                                           uint64_t key) { |                                           uint64_t key) { | ||||||
|   vieter_tree_node *target; |   vieter_tree_node *target; | ||||||
|  |  | ||||||
|  | @ -37,4 +37,7 @@ void vieter_tree_node_set(vieter_tree_node *node, vieter_node_flag flag); | ||||||
| void vieter_tree_node_unset(vieter_tree_node *node, vieter_node_flag flag); | void vieter_tree_node_unset(vieter_tree_node *node, vieter_node_flag flag); | ||||||
| bool vieter_tree_node_get(vieter_tree_node *node, vieter_node_flag flag); | bool vieter_tree_node_get(vieter_tree_node *node, vieter_node_flag flag); | ||||||
| 
 | 
 | ||||||
|  | void vieter_tree_node_add_child(vieter_tree_node *parent, uint64_t key, | ||||||
|  |                                 vieter_tree_node *child); | ||||||
|  | 
 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | @ -16,6 +16,7 @@ vieter_tree_error vieter_tree_insert(vieter_tree *tree, uint64_t key, | ||||||
|     tree->root = vieter_tree_node_init(); |     tree->root = vieter_tree_node_init(); | ||||||
|     tree->root->key = key; |     tree->root->key = key; | ||||||
|     tree->root->data = data; |     tree->root->data = data; | ||||||
|  |     vieter_tree_node_set(tree->root, vieter_node_black); | ||||||
|     tree->size = 1; |     tree->size = 1; | ||||||
| 
 | 
 | ||||||
|     return vieter_tree_ok; |     return vieter_tree_ok; | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue