Node * node_uncle(Node * n) { Node * g = node_grandparent(n); if (!g) { return NULL; } if (n->parent == g->left) { return g->right; } else { return g->left; } }
void map_insert(map_t *map, mapkey_t key, void *p) { allocator_t *alloc = map->allocator; mapnode_t *parent = map->root; mapnode_t **slot = &map->root; mapnode_t *insert; while (parent != NIL) { int comparison = map->ops.compare_key(key, parent->key); if (comparison == 0) { map->ops.destroy_value(parent->p, alloc); parent->p = map->ops.copy_value(p, alloc); return; } else if (comparison < 0) { if (parent->left != NIL) { parent = parent->left; continue; } else { slot = &parent->left; break; } } else { if (parent->right != NIL) { parent = parent->right; continue; } else { slot = &parent->right; break; } } } map->size += 1; insert = (mapnode_t *)com_malloc(map->allocator, sizeof(mapnode_t)); insert->left = insert->right = NIL; insert->key = map->ops.copy_key(key, alloc); insert->p = map->ops.copy_value(p, alloc); insert->color = RED; insert->parent = parent; *slot = insert; while (IS_RED(insert->parent) && node_grandparent(insert) != NIL) { mapnode_t *uncle = node_sibling(insert->parent); if (IS_RED(uncle)) { insert->parent->color = BLACK; uncle->color = BLACK; uncle->parent->color = RED; insert = uncle->parent; } else { int insleft = IS_LEFT(insert); int parleft = IS_LEFT(insert->parent); if (!insleft && parleft) { insert = insert->parent; node_rotate_left(map, insert); } else if (insleft && !parleft) { insert = insert->parent; node_rotate_right(map, insert); } insert->parent->parent->color = RED; insert->parent->color = BLACK; if (parleft) node_rotate_right(map, insert->parent->parent); else node_rotate_left(map, insert->parent->parent); } } map->root->color = BLACK; #if !defined(NDEBUG) map_test(map->root); #endif }