diff --git a/src/tree.c b/src/tree.c index 5baa60d16479070c55e7c855eac20367c6aa429d..3ed96d36aba4ecce4c2751dc2eae5d975f425d66 100644 --- a/src/tree.c +++ b/src/tree.c @@ -111,6 +111,7 @@ struct tree_t * new_tree(int balanced, int (*preceed)(const void *, const void * tree->preceed = preceed; tree->viewKey = viewKey; tree->viewData = viewData; + tree->freeKey = freeKey; tree->freeData = freeData; tree->numelm = 0; tree->root = NULL; @@ -419,37 +420,27 @@ struct tree_node_t * tree_find_node(struct tree_node_t * curr, void * key, int ( } struct tree_node_t * tree_find_predecessor(struct tree_node_t * curr, void * key, int (*preceed)(const void *, const void *)) { - assert(!tree_node_is_empty(curr)); - - struct tree_node_t * prev = NULL; - - while (curr) { - if (preceed(key, curr->key) > 0) { - prev = curr; - curr = curr->right; - } else { - curr = curr->left; - } - } + if (curr == NULL) return NULL; - return prev; + if (preceed(get_tree_node_key(curr), key) >= 0) + { + if (!tree_node_is_empty(get_left(curr))) + return tree_max(curr); + return NULL; + } + else return tree_find_predecessor(get_left(curr), key, preceed); } struct tree_node_t * tree_find_successor(struct tree_node_t * curr, void * key, int (*preceed)(const void *, const void *)) { - assert(!tree_node_is_empty(curr)); - // A FAIRE - struct tree_node_t * succ = NULL; - - while (curr) { - if (preceed(key, curr->key) < 0) { - succ = curr; - curr = curr->left; - } else { - curr = curr->right; - } - } + if (curr == NULL) return NULL; - return succ; + if (preceed(get_tree_node_key(curr), key) <= 0) + { + if (!tree_node_is_empty(get_right(curr))) + return tree_min(curr); + return NULL; + } + else return tree_find_successor(get_right(curr), key, preceed); } /** @@ -489,9 +480,24 @@ static struct tree_node_t * remove_tree_node(struct tree_node_t * curr, void * k { curr->right = remove_tree_node(curr->right, key, data, balanced, preceed); } else { + struct tree_node_t* orphan = get_left(curr)? get_left(curr) : get_right(curr); + if (get_right(curr) && get_left(curr)) + { + // On remplace curr par le plus proche supérieur puis recursion pour l'enlever et on attend les rotations + struct tree_node_t* sup = tree_find_successor(curr, key, preceed); + set_tree_node_key(curr, get_tree_node_key(sup)); + set_tree_node_data(curr, get_tree_node_data(sup)); + set_right(curr, remove_tree_node(get_right(curr), get_tree_node_key(sup), data, balanced, preceed)); + } + else if (orphan) + { + // Cas simple, on réattache et on attend le rééquilibrage + set_tree_node_key(curr, get_tree_node_key(orphan)); + set_tree_node_data(curr, get_tree_node_data(orphan)); + set_left(curr, get_left(orphan)); + set_right(curr, get_right(orphan)); + } *data = get_tree_node_data(curr); - free(curr); - return NULL; } } @@ -538,7 +544,10 @@ static struct tree_node_t * remove_tree_node(struct tree_node_t * curr, void * k */ void * tree_remove(struct tree_t * T, void * key) { void* data = NULL; - remove_tree_node(get_root(T), key, &data, 0, T->preceed); - T->freeKey(key); + struct tree_node_t* node = remove_tree_node(get_root(T), key, &data, 0, T->preceed); + if (node) + { + T->freeKey(key); + } return data; }