void* avltree_remove(avltree_t* me, void* k) { int i; for (i = 0; i < me->size; ) { long r; node_t *n; n = &me->nodes[i]; /* couldn't find it */ if (!n->key) return NULL; r = me->cmp(n->key, k); if (r == 0) { /* replacement */ int rep; me->count -= 1; k = n->key; rep = __previous_ordered_node(me, i); if (-1 == rep) { /* make sure the node is now blank */ n->key = NULL; } else { /* have r's left node become right node of r's parent. * NOTE: r by definition shouldn't have a right child */ __shift_up(me, __child_l(rep), __child_r(__parent(rep))); /* have r replace deleted node */ __shift_up(me, rep, i); } if (i != 0) __rebalance(me, __parent(i)); return k; } else if (r < 0) { i = __child_l(i); } else if (r > 0) { i = __child_r(i); } else { assert(0); } } /* couldn't find it */ return NULL; }
static int __pushup(heap_t * hp, int idx) { while (1) { int parent, compare; /* we are now the root node */ if (0 == idx) return idx; parent = __parent(idx); compare = hp->cmp(hp->array[idx], hp->array[parent], hp->udata); /* we are smaller than the parent */ if (compare < 0) { return -1; } else { __swap(hp, idx, parent); } idx = parent; } return idx; }
static void __rebalance(avltree_t* me, int idx) { while (1) { if (2 <= __height(me, __child_l(idx)) - __height(me, __child_r(idx))) { int bf_l; bf_l = __height(me, __child_l(__child_l(idx))) - __height(me, __child_r(__child_l(idx))); if (bf_l == -1) { avltree_rotate_left(me, __child_l(idx)); avltree_rotate_right(me, __child_l(idx)); } else { avltree_rotate_right(me, __child_l(idx)); } } else if (-2 >= __height(me, __child_l(idx)) - __height(me, __child_r(idx))) { int bf_r; bf_r = __height(me, __child_l(__child_r(idx))) - __height(me, __child_r(__child_r(idx))); if (bf_r == -1) { avltree_rotate_left(me, __child_r(idx)); } else { avltree_rotate_right(me, __child_r(idx)); avltree_rotate_left(me, __child_r(idx)); } } if (0 == idx) break; idx = __parent(idx); } }
void avltree_rotate_left(avltree_t* me, int idx) { int p; p = __parent(idx); /* A Partial * Move Y out of the way so that X can take its spot */ __shift_down(me, __child_l(p), __child_l(__child_l(p))); memcpy(&me->nodes[__child_l(p)], &me->nodes[p], sizeof(node_t)); if (me->shift_down_callback) me->shift_down_callback( p, __child_l(p), me->shift_up_callback_user); /* B */ __shift_down(me, __child_l(idx), __child_r(__child_l(p))); me->nodes[__child_l(idx)].key = NULL; /* A Final * Move Y into X's old spot */ __shift_up(me, idx, p); }
void rebalance(avltree_t* me, int position) { return __rebalance(me, __parent(position)); }