diff --git a/src/tree.c b/src/tree.c index 5baa60d16479070c55e7c855eac20367c6aa429d..55e01ca72b78f5702e3e69b86f5593e1a0aa51ab 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; @@ -352,7 +353,7 @@ static struct tree_node_t * insert_into_tree_node(struct tree_node_t * curr, voi // 6 cas int FEX = get_bfactor(curr); - if(FEX == 2) + if(FEX > 1) { int FEY = get_bfactor(get_left(curr)); if(FEY == 1 || FEY == 0) @@ -365,7 +366,7 @@ static struct tree_node_t * insert_into_tree_node(struct tree_node_t * curr, voi curr = rotate_right(curr); } } - else if(FEX == -2) + else if(FEX < -1) { int FEY = get_bfactor(get_right(curr)); if(FEY == -1 || FEY == 0) @@ -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; } } @@ -502,7 +508,7 @@ static struct tree_node_t * remove_tree_node(struct tree_node_t * curr, void * k // 6 cas int FEX = get_bfactor(curr); - if(FEX == 2) + if(FEX > 1) { int FEY = get_bfactor(get_left(curr)); if(FEY == 1 || FEY == 0) @@ -515,7 +521,7 @@ static struct tree_node_t * remove_tree_node(struct tree_node_t * curr, void * k curr = rotate_right(curr); } } - else if(FEX == -2) + else if(FEX < -1) { int FEY = get_bfactor(get_right(curr)); if(FEY == -1 || FEY == 0) @@ -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, tree_is_balanced(T), T->preceed); + if (node) + { + T->freeKey(key); + } return data; }