static HklTreeNode* hkl_treenode_remove(HklTree* tree, HklTreeNode* node, HklString* key) { assert(node != NULL); assert(key != NULL); // If key < current node key, go left if (hkl_string_compare(key, node->pair->key) < 0) { if (node->left != NULL) { if (!hkl_treenode_isred(node->left) && hkl_treenode_isred(node->left->left)) node = hkl_treenode_redleft(node); node->left = hkl_treenode_remove(tree, node->left, key); } } else { if (hkl_treenode_isred(node->left)) node = hkl_treenode_rotright(node); if (hkl_string_compare(key, node->pair->key) == 0 && (node->right == NULL)) { --tree->size; hkl_treenode_free(node); return NULL; } if (node->right != NULL) { if (!hkl_treenode_isred(node->right) && !hkl_treenode_isred(node->right->left)) node = hkl_treenode_redright(node); if (hkl_string_compare(key, node->pair->key) == 0) { node->pair->value = hkl_treenode_findmin(node->right)->pair->value; node->right = hkl_treenode_removemin(tree, node->right); } else { node->right = hkl_treenode_remove(tree, node->right, key); } } } return hkl_treenode_fixup(node); }
static HklTreeNode* hkl_treenode_fixup(HklTreeNode* node) { assert(node != NULL); if (hkl_treenode_isred(node->right)) node = hkl_treenode_rotleft(node); if (hkl_treenode_isred(node->left) && hkl_treenode_isred(node->left->left)) node = hkl_treenode_rotright(node); if (hkl_treenode_isred(node->left)) hkl_treenode_colorflip(node); return node; }
static HklTreeNode* hkl_treenode_removemin(HklTreeNode* node) { if (node->left == NULL) { hkl_treenode_free(node); return NULL; } if (!hkl_treenode_isred(node->left) && !hkl_treenode_isred(node->left->left)) node = hkl_treenode_redleft(node); node->left = hkl_treenode_removemin(node->left); return hkl_treenode_fixup(node); }
static HklTreeNode* hkl_treenode_move_pair(HklTreeNode* node, HklPair* pair) { assert(pair != NULL); if (node == NULL) return hkl_treenode_new_from_pair(pair); if (hkl_treenode_isred(node->left) && hkl_treenode_isred(node->right)) hkl_treenode_colorflip(node); int cmp = hkl_string_compare(node->pair->key, pair->key); if (cmp == 0) { // This shouldnt happen since we only move into empty trees assert(false); node->pair = pair; } else if (cmp < 0) node->left = hkl_treenode_move_pair(node->left, pair); else node->right = hkl_treenode_move_pair(node->right, pair); if (hkl_treenode_isred(node->right) && !hkl_treenode_isred(node->left)) node = hkl_treenode_rotleft(node); if (hkl_treenode_isred(node->left) && hkl_treenode_isred(node->left->left)) node = hkl_treenode_rotright(node); return node; }
static HklTreeNode* hkl_treenode_insert(HklTree* tree, HklTreeNode* node, HklString* key, void* value) { assert(key != NULL); // Insert in an empty node if (node == NULL) { ++tree->size; return hkl_treenode_new(key, value); } if (hkl_treenode_isred(node->left) && hkl_treenode_isred(node->right)) hkl_treenode_colorflip(node); int cmp = hkl_string_compare(node->pair->key, key); if (cmp == 0) node->pair->value = value; else if (cmp < 0) node->left = hkl_treenode_insert(tree, node->left, key, value); else node->right = hkl_treenode_insert(tree, node->right, key, value); if (hkl_treenode_isred(node->right) && !hkl_treenode_isred(node->left)) node = hkl_treenode_rotleft(node); if (hkl_treenode_isred(node->left) && hkl_treenode_isred(node->left->left)) node = hkl_treenode_rotright(node); return node; }
static HklTreeNode* hkl_treenode_redright(HklTreeNode* node) { assert(node != NULL); hkl_treenode_colorflip(node); if (node->left != NULL && hkl_treenode_isred(node->left->left)) { node = hkl_treenode_rotright(node); hkl_treenode_colorflip(node); } return node; }