/*! * Duplicate the entire sub-tree rooted at the given node * * \param node The sub-tree root * * \return A pointer to the duplicated sub-tree root */ rbnode_t * rbnode_duplicate ( rbnode_t * node ) { /* Create a node of the same color, containing the same object */ rbnode_t * dup_node = rbnode_create(node->object, node->color); if (!dup_node) return NULL; /* Duplicate the children recursively */ if (node->right) { dup_node->right = rbnode_duplicate (node->right); dup_node->right->parent = dup_node; } else { dup_node->right = NULL; } if (node->left) { dup_node->left = rbnode_duplicate(node->left); dup_node->left->parent = dup_node; } else { dup_node->left = NULL; } /* Return the duplicated node */ return dup_node; }
void map_insert(map* tree, const char* key, void* data, const int tag) { rbnode* node = rbnode_create(key, data, tag); rbnode* iterator; int comparison; int fail = 0; if (tree->root == 0) { tree_set_root(tree, node); tree->size = 0; } else { iterator = tree->root; while (iterator != 0) { comparison = strcmp(key, iterator->data.key); /* key already exists */ if (comparison == 0) { fail = 1; iterator = 0; } /* new key < iterator's key */ else if (comparison < 0) { /* left of iterator is free */ if (iterator->left != 0) { iterator = iterator->left; } /* left of iterator is occupied */ else { rbnode_set_left_child(iterator, node); iterator = 0; } } /* new key > iterator's key */ else { /* right of iterator is free */ if (iterator->right != 0) { iterator = iterator->right; } /* right of iterator is occupied */ else { rbnode_set_right_child(iterator, node); iterator = 0; } } } } /* tree requires rebalancing */ if (!fail) { tree->size++; map_insert_balance(tree, node); } }
/*! * Insert a new object to the tree as the a predecessor of a given node * * \param tree The tree * * \return The new node */ rbnode_t * rbtree_insert_predecessor_object_at ( rbtree_t * tree, rbnode_t * at_node, void * object ) { rbnode_t * parent; rbnode_t * new_node; if (!(tree->root)) { /* Assign a new root node. Notice that the root is always black */ new_node = rbnode_create(object, RB_BLACK); if (!new_node) return NULL; tree->root = new_node; tree->size = 1; new_node->tree = tree; return new_node; } /* Insert the new object as a red leaf, being the predecessor of at_node */ new_node = rbnode_create(object, RB_RED); if (!new_node) return NULL; if (!at_node) { /* The new node should become the tree maximum: Place is as the right * child of the current maximal leaf. */ parent = rbnode_maximum(tree->root); parent->right = new_node; } else { /* Make sure the insertion does not violate the tree order */ /* In case given node has no left child, place the new node as its * left child. Otherwise, place it at the rightmost position at the * sub-tree rooted at its left side. */ if (!(at_node->left)) { parent = at_node; parent->left = new_node; } else { parent = rbnode_maximum (at_node->left); parent->right = new_node; } } new_node->parent = parent; /* Mark that a new node was added */ tree->size++; /* Fix up the tree properties */ rbtree_insert_fixup(tree, new_node); new_node->tree = tree; return new_node; }
/*! * Insert an object to the tree [takes O(log n) operations] * * \param tree The tree * * \param object The object to be inserted * * \return the inserted object node */ rbnode_t * rbtree_insert_object ( rbtree_t * tree, void * object ) { rbnode_t * cur_node; rbnode_t * new_node; if (!(tree->root)) { /* * Assign a new root node. * Notice that the root is always black */ new_node = rbnode_create(object, RB_BLACK); if (!new_node) return NULL; tree->root = new_node; tree->size = 1; new_node->tree = tree; return new_node; } /* Find a place for the new object, and insert it as a red leaf */ cur_node = tree->root; new_node = rbnode_create(object, RB_RED); if (!new_node) return NULL; while (cur_node) { /* * Compare inserted object with the object stored * in the current node */ if ((tree->compare)(object, cur_node->object) > 0) { if (!(cur_node->left)) { /* * Insert the new leaf as the left * child of the current node */ cur_node->left = new_node; new_node->parent = cur_node; /* Terminate the while loop */ cur_node = NULL; } else { /* Go to the left sub-tree */ cur_node = cur_node->left; } } else { if (!(cur_node->right)) { /* * Insert the new leaf as the right * child of the current node */ cur_node->right = new_node; new_node->parent = cur_node; /* Terminate the while loop */ cur_node = NULL; } else { /* Go to the right sub-tree */ cur_node = cur_node->right; } } } /* Mark that a new node was added */ tree->size++; /* Fix up the tree properties */ rbtree_insert_fixup(tree, new_node); new_node->tree = tree; return new_node; }