avl_node * avl_new_avl_node (void * key, avl_node * parent) { avl_node * node = (avl_node *) malloc (sizeof (avl_node)); if (!node) { return NULL; } else { node->parent = parent; node->key = key; node->left = NULL; node->right = NULL; node->rank_and_balance = 0; AVL_SET_BALANCE (node, 0); AVL_SET_RANK (node, 1); return node; } }
avl_node * avl_node_new (void * key, avl_node * parent) { avl_node * node = (avl_node *) malloc (sizeof (avl_node)); if (!node) abort(); node->parent = parent; node->key = key; node->left = NULL; node->right = NULL; node->rank_and_balance = 0; AVL_SET_BALANCE (node, 0); AVL_SET_RANK (node, 1); #ifdef HAVE_AVL_NODE_LOCK thread_rwlock_create(&node->rwlock); #endif return node; }
int avl_delete(avl_tree *tree, void *key, avl_free_key_fun_type free_key_fun) { avl_node *x, *y, *p, *q, *r, *top, *x_child; int shortened_side, shorter; x = tree->root->right; if (!x) { return -1; } while (1) { int compare_result = tree->compare_fun (tree->compare_arg, key, x->key); if (compare_result < 0) { /* move left * We will be deleting from the left, adjust this node's * rank accordingly */ AVL_SET_RANK (x, (AVL_GET_RANK(x) - 1)); if (x->left) { x = x->left; } else { /* Oops! now we have to undo the rank changes * all the way up the tree */ AVL_SET_RANK(x, (AVL_GET_RANK (x) + 1)); while (x != tree->root->right) { if (x->parent->left == x) { AVL_SET_RANK(x->parent, (AVL_GET_RANK (x->parent) + 1)); } x = x->parent; } return -1; /* key not in tree */ } } else if (compare_result > 0) { /* move right */ if (x->right) { x = x->right; } else { AVL_SET_RANK(x, (AVL_GET_RANK (x) + 1)); while (x != tree->root->right) { if (x->parent->left == x) { AVL_SET_RANK(x->parent, (AVL_GET_RANK (x->parent) + 1)); } x = x->parent; } return -1; /* key not in tree */ } } else { break; } } if (x->left && x->right) { void * temp_key; /* The complicated case. * reduce this to the simple case where we are deleting * a node with at most one child. */ /* find the immediate predecessor <y> */ y = x->left; while (y->right) { y = y->right; } /* swap <x> with <y> */ temp_key = x->key; x->key = y->key; y->key = temp_key; /* we know <x>'s left subtree lost a node because that's * where we took it from */ AVL_SET_RANK (x, (AVL_GET_RANK (x) - 1)); x = y; } /* now <x> has at most one child * scoot this child into the place of <x> */ if (x->left) { x_child = x->left; x_child->parent = x->parent; } else if (x->right) { x_child = x->right; x_child->parent = x->parent; } else { x_child = NULL; } /* now tell <x>'s parent that a grandchild became a child */ if (x == x->parent->left) { x->parent->left = x_child; shortened_side = -1; } else { x->parent->right = x_child; shortened_side = +1; } /* * the height of the subtree <x> * has now been shortened. climb back up * the tree, rotating when necessary to adjust * for the change. */ shorter = 1; p = x->parent; /* return the key and node to storage */ if (free_key_fun) free_key_fun (x->key); #ifdef HAVE_AVL_NODE_LOCK thread_rwlock_destroy (&x->rwlock); #endif free (x); while (shorter && p->parent) { /* case 1: height unchanged */ if (AVL_GET_BALANCE(p) == 0) { if (shortened_side == -1) { /* we removed a left child, the tree is now heavier * on the right */ AVL_SET_BALANCE (p, +1); } else { /* we removed a right child, the tree is now heavier * on the left */ AVL_SET_BALANCE (p, -1); } shorter = 0; } else if (AVL_GET_BALANCE (p) == shortened_side) { /* case 2: taller subtree shortened, height reduced */ AVL_SET_BALANCE (p, 0); } else { /* case 3: shorter subtree shortened */ top = p->parent; /* set <q> to the taller of the two subtrees of <p> */ if (shortened_side == 1) { q = p->left; } else { q = p->right; } if (AVL_GET_BALANCE (q) == 0) { /* case 3a: height unchanged */ if (shortened_side == -1) { /* single rotate left */ q->parent = p->parent; p->right = q->left; if (q->left) { q->left->parent = p; } q->left = p; p->parent = q; AVL_SET_RANK (q, (AVL_GET_RANK (q) + AVL_GET_RANK (p))); } else { /* single rotate right */ q->parent = p->parent; p->left = q->right; if (q->right) { q->right->parent = p; } q->right = p; p->parent = q; AVL_SET_RANK (p, (AVL_GET_RANK (p) - AVL_GET_RANK (q))); } shorter = 0; AVL_SET_BALANCE (q, shortened_side); AVL_SET_BALANCE (p, (- shortened_side)); } else if (AVL_GET_BALANCE (q) == AVL_GET_BALANCE (p)) { /* case 3b: height reduced */ if (shortened_side == -1) { /* single rotate left */ q->parent = p->parent; p->right = q->left; if (q->left) { q->left->parent = p; } q->left = p; p->parent = q; AVL_SET_RANK (q, (AVL_GET_RANK (q) + AVL_GET_RANK (p))); } else { /* single rotate right */ q->parent = p->parent; p->left = q->right; if (q->right) { q->right->parent = p; } q->right = p; p->parent = q; AVL_SET_RANK (p, (AVL_GET_RANK (p) - AVL_GET_RANK (q))); } shorter = 1; AVL_SET_BALANCE (q, 0); AVL_SET_BALANCE (p, 0); } else { /* case 3c: height reduced, balance factors opposite */ if (shortened_side == 1) { /* double rotate right */ /* first, a left rotation around q */ r = q->right; r->parent = p->parent; q->right = r->left; if (r->left) { r->left->parent = q; } r->left = q; q->parent = r; /* now, a right rotation around p */ p->left = r->right; if (r->right) { r->right->parent = p; } r->right = p; p->parent = r; AVL_SET_RANK (r, (AVL_GET_RANK (r) + AVL_GET_RANK (q))); AVL_SET_RANK (p, (AVL_GET_RANK (p) - AVL_GET_RANK (r))); } else { /* double rotate left */ /* first, a right rotation around q */ r = q->left; r->parent = p->parent; q->left = r->right; if (r->right) { r->right->parent = q; } r->right = q; q->parent = r; /* now a left rotation around p */ p->right = r->left; if (r->left) { r->left->parent = p; } r->left = p; p->parent = r; AVL_SET_RANK (q, (AVL_GET_RANK (q) - AVL_GET_RANK (r))); AVL_SET_RANK (r, (AVL_GET_RANK (r) + AVL_GET_RANK (p))); } if (AVL_GET_BALANCE (r) == shortened_side) { AVL_SET_BALANCE (q, (- shortened_side)); AVL_SET_BALANCE (p, 0); } else if (AVL_GET_BALANCE (r) == (- shortened_side)) { AVL_SET_BALANCE (q, 0); AVL_SET_BALANCE (p, shortened_side); } else { AVL_SET_BALANCE (q, 0); AVL_SET_BALANCE (p, 0); } AVL_SET_BALANCE (r, 0); q = r; } /* a rotation has caused <q> (or <r> in case 3c) to become * the root. let <p>'s former parent know this. */ if (top->left == p) { top->left = q; } else { top->right = q; } /* end case 3 */ p = q; } x = p; p = x->parent; /* shortened_side tells us which side we came up from */ if (x == p->left) { shortened_side = -1; } else { shortened_side = +1; } } /* end while(shorter) */ /* when we're all done, we're one shorter */ tree->length = tree->length - 1; return (0); }
int avl_insert (avl_tree * ob, void * key) { if (!(ob->root->right)) { avl_node * node = avl_node_new (key, ob->root); if (!node) { return -1; } else { ob->root->right = node; ob->length = ob->length + 1; return 0; } } else { /* not self.right == None */ avl_node *t, *p, *s, *q, *r; int a; t = ob->root; s = p = t->right; while (1) { if (ob->compare_fun (ob->compare_arg, key, p->key) < 1) { /* move left */ AVL_SET_RANK (p, (AVL_GET_RANK (p) + 1)); q = p->left; if (!q) { /* insert */ avl_node * q_node = avl_node_new (key, p); if (!q_node) { return (-1); } else { q = q_node; p->left = q; break; } } else if (AVL_GET_BALANCE(q)) { t = p; s = q; } p = q; } else { /* move right */ q = p->right; if (!q) { /* insert */ avl_node * q_node = avl_node_new (key, p); if (!q_node) { return -1; } else { q = q_node; p->right = q; break; } } else if (AVL_GET_BALANCE(q)) { t = p; s = q; } p = q; } } ob->length = ob->length + 1; /* adjust balance factors */ if (ob->compare_fun (ob->compare_arg, key, s->key) < 1) { r = p = s->left; } else { r = p = s->right; } while (p != q) { if (ob->compare_fun (ob->compare_arg, key, p->key) < 1) { AVL_SET_BALANCE (p, -1); p = p->left; } else { AVL_SET_BALANCE (p, +1); p = p->right; } } /* balancing act */ if (ob->compare_fun (ob->compare_arg, key, s->key) < 1) { a = -1; } else { a = +1; } if (AVL_GET_BALANCE (s) == 0) { AVL_SET_BALANCE (s, a); ob->height = ob->height + 1; return 0; } else if (AVL_GET_BALANCE (s) == -a) { AVL_SET_BALANCE (s, 0); return 0; } else if (AVL_GET_BALANCE(s) == a) { if (AVL_GET_BALANCE (r) == a) { /* single rotation */ p = r; if (a == -1) { s->left = r->right; if (r->right) { r->right->parent = s; } r->right = s; s->parent = r; AVL_SET_RANK (s, (AVL_GET_RANK (s) - AVL_GET_RANK (r))); } else { s->right = r->left; if (r->left) { r->left->parent = s; } r->left = s; s->parent = r; AVL_SET_RANK (r, (AVL_GET_RANK (r) + AVL_GET_RANK (s))); } AVL_SET_BALANCE (s, 0); AVL_SET_BALANCE (r, 0); } else if (AVL_GET_BALANCE (r) == -a) { /* double rotation */ if (a == -1) { p = r->right; r->right = p->left; if (p->left) { p->left->parent = r; } p->left = r; r->parent = p; s->left = p->right; if (p->right) { p->right->parent = s; } p->right = s; s->parent = p; AVL_SET_RANK (p, (AVL_GET_RANK (p) + AVL_GET_RANK (r))); AVL_SET_RANK (s, (AVL_GET_RANK (s) - AVL_GET_RANK (p))); } else { p = r->left; r->left = p->right; if (p->right) { p->right->parent = r; } p->right = r; r->parent = p; s->right = p->left; if (p->left) { p->left->parent = s; } p->left = s; s->parent = p; AVL_SET_RANK (r, (AVL_GET_RANK (r) - AVL_GET_RANK (p))); AVL_SET_RANK (p, (AVL_GET_RANK (p) + AVL_GET_RANK (s))); } if (AVL_GET_BALANCE (p) == a) { AVL_SET_BALANCE (s, -a); AVL_SET_BALANCE (r, 0); } else if (AVL_GET_BALANCE (p) == -a) { AVL_SET_BALANCE (s, 0); AVL_SET_BALANCE (r, a); } else { AVL_SET_BALANCE (s, 0); AVL_SET_BALANCE (r, 0); } AVL_SET_BALANCE (p, 0); } /* finishing touch */ if (s == t->right) { t->right = p; } else { t->left = p; } p->parent = t; } } return 0; }