/* The tree is overbalanced to the right, so we rotate nodes to the left */ static int tree_node_rotate_left(Edata_Tree *tree, Edata_Tree_Node *top_node) { Edata_Tree_Node *temp; CHECK_PARAM_POINTER_RETURN("top_node", top_node, FALSE); /* * The right branch's left branch becomes the nodes right branch, * the right branch becomes the top node, and the node becomes the * left branch. */ temp = top_node->left_child; top_node->left_child = temp->right_child; temp->right_child = top_node; /* Make sure the nodes know who their new parents are. */ temp->parent = top_node->parent; if (temp->parent == NULL) tree->tree = temp; else { if (temp->parent->left_child == top_node) temp->parent->left_child = temp; else temp->parent->right_child = temp; } top_node->parent = temp; /* And recalculate node heights */ tree_node_balance(tree, top_node); tree_node_balance(tree, temp); return TRUE; }
/** * Set the value associated with key to @a value. * @param tree The tree that contains the key/value pair. * @param key The key to identify which node to set a value. * @param value Value to set the found node. * @return TRUE if successful, FALSE if not. */ EAPI int edata_tree_set(Edata_Tree *tree, void *key, void *value) { Edata_Tree_Node *node = NULL; CHECK_PARAM_POINTER_RETURN("tree", tree, FALSE); node = tree_node_find(tree, key); if (!node) { node = edata_tree_node_new(); edata_tree_node_key_set(node, key); if (!edata_tree_node_add(tree, node)) return FALSE; } else { if (tree->free_key) tree->free_key(key); if (node->value && tree->free_value) tree->free_value(node->value); } edata_tree_node_value_set(node, value); for (; node; node = node->parent) tree_node_balance(tree, node); return TRUE; }
static DirectNode * tree_node_insert (DirectTree *tree, DirectNode *node, void *key, void *value, int *inserted) { int cmp; int old_balance; if (!node) { *inserted = 1; return tree_node_new (tree, key, value); } cmp = key - node->key; if (cmp == 0) { node->value = value; return node; } if (cmp < 0) { if (node->left) { old_balance = node->left->balance; node->left = tree_node_insert (tree, node->left, key, value, inserted); if ((old_balance != node->left->balance) && node->left->balance) node->balance -= 1; } else { *inserted = 1; node->left = tree_node_new (tree, key, value); node->balance -= 1; } } else if (cmp > 0) { if (node->right) { old_balance = node->right->balance; node->right = tree_node_insert (tree, node->right, key, value, inserted); if ((old_balance != node->right->balance) && node->right->balance) node->balance += 1; } else { *inserted = 1; node->right = tree_node_new (tree, key, value); node->balance += 1; } } if (*inserted && (node->balance < -1 || node->balance > 1)) node = tree_node_balance (node); return node; }
/** * Remove the node from the tree. * @param tree The tree to remove @a node from. * @param node The node to remove from @a tree. * @return TRUE on a successful remove, FALSE otherwise. */ EAPI int edata_tree_node_remove(Edata_Tree *tree, Edata_Tree_Node *node) { Edata_Tree_Node *traverse; CHECK_PARAM_POINTER_RETURN("tree", tree, FALSE); CHECK_PARAM_POINTER_RETURN("node", node, FALSE); /* * Find the nearest value to the balanced one. */ if (node->left_child) { traverse = node->left_child; /* Now work our way down right side of the traverse node. * This will give us the node with the next closest value * to the current node. If traverse had no right node, then * this will stop at node's left node. */ while (traverse->right_child) { traverse = traverse->right_child; } /* * Hook any dropped leaves into the moved nodes spot */ if (traverse->parent) traverse->parent->left_child = traverse->left_child; } else if (node->right_child) { traverse = node->right_child; /* Now work our way down left side of the traverse node. * This will give us the node with the next closest value * to the current node. If traverse had no left node, then * this will stop at node's right node. */ while (traverse->left_child) { traverse = traverse->left_child; } /* * Hook any dropped leaves into the moved nodes spot */ if (traverse->right_child) traverse->right_child->parent = traverse->parent; if (traverse->parent) traverse->parent->right_child = traverse->right_child; else tree->tree = traverse->right_child; } else traverse = NULL; if (traverse) { /* * Ensure that we don't get a recursive reference. */ if (node->right_child && node->right_child != traverse) { node->right_child->parent = traverse; traverse->right_child = node->right_child; } if (node->left_child && node->left_child != traverse) { node->left_child->parent = traverse; traverse->left_child = node->left_child; } /* * Unlink the node to be moved from it's parent. */ if (traverse->parent) { if (traverse->parent->left_child == traverse) traverse->parent->left_child = NULL; else traverse->parent->right_child = NULL; } traverse->parent = node->parent; } if (node->parent) { if (node == node->parent->left_child) node->parent->left_child = traverse; else node->parent->right_child = traverse; } if (tree->tree == node) tree->tree = traverse; node->parent = node->left_child = node->right_child = NULL; /* * Rebalance the tree to ensure short search paths. */ while (traverse) { tree_node_balance(tree, traverse); traverse = traverse->parent; } return TRUE; }