static struct avl_node *avl_rotate_single(struct avl_node *root, int dir) { struct avl_node *save; int rlh, rrh, slh; /* Rotate */ save = root->link[!dir]; root->link[!dir] = save->link[dir]; if (root->link[!dir]) root->link[!dir]->up = root; save->link[dir] = root; if ( root ) root->up = save; /* Update balance factors */ rlh = avl_height(root->link[0]); rrh = avl_height(root->link[1]); slh = avl_height(save->link[!dir]); root->balance = avl_max(rlh, rrh) + 1; save->balance = avl_max(slh, root->balance) + 1; return save; }
static node_t * avl_single(node_t *root, int dir) { node_t *save = root->link[!dir]; int rlh, rrh, slh; root->link[!dir] = save->link[dir]; save->link[dir] = root; rlh = height(root->link[0]); rrh = height(root->link[1]); slh = height(save->link[!dir]); BALANCE(root) = avl_max(rlh, rrh) + 1; BALANCE(save) = avl_max(slh, BALANCE(root)) + 1; return save; }
extern int avl_remove(node_t **rootaddr, PyObject *key) { node_t *root = *rootaddr; int cmp_res; if (root != NULL) { node_t *it, *up[32]; int upd[32], top = 0; it = root; for (;;) { if (it == NULL) return 0; cmp_res = ct_compare(KEY(it), key); if (cmp_res == 0) break; upd[top] = (cmp_res < 0); up[top++] = it; it = it->link[upd[top - 1]]; } if (it->link[0] == NULL || it->link[1] == NULL) { int dir = it->link[0] == NULL; if (top != 0) up[top - 1]->link[upd[top - 1]] = it->link[dir]; else root = it->link[dir]; ct_delete_node(it); } else { node_t *heir = it->link[1]; upd[top] = 1; up[top++] = it; while ( heir->link[0] != NULL ) { upd[top] = 0; up[top++] = heir; heir = heir->link[0]; } ct_swap_data(it, heir); up[top - 1]->link[up[top - 1] == it] = heir->link[1]; ct_delete_node(heir); } while (--top >= 0) { int lh = height(up[top]->link[upd[top]]); int rh = height(up[top]->link[!upd[top]]); int max = avl_max(lh, rh); BALANCE(up[top]) = max + 1; if (lh - rh == -1) break; if (lh - rh <= -2) { node_t *a = up[top]->link[!upd[top]]->link[upd[top]]; node_t *b = up[top]->link[!upd[top]]->link[!upd[top]]; if (height(a) <= height(b)) up[top] = avl_single(up[top], upd[top]); else up[top] = avl_double(up[top], upd[top]); if (top != 0) up[top - 1]->link[upd[top - 1]] = up[top]; else root = up[0]; } } } (*rootaddr) = root; return 1; }
extern int avl_insert(node_t **rootaddr, PyObject *key, PyObject *value) { node_t *root = *rootaddr; if (root == NULL) { root = avl_new_node(key, value); if (root == NULL) return -1; } else { node_t *it, *up[32]; int upd[32], top = 0; int done = 0; int cmp_res; it = root; for (;;) { cmp_res = ct_compare(KEY(it), key); if (cmp_res == 0) { Py_XDECREF(VALUE(it)); VALUE(it) = value; Py_INCREF(value); return 0; } upd[top] = (cmp_res < 0); up[top++] = it; if (it->link[upd[top - 1]] == NULL) break; it = it->link[upd[top - 1]]; } it->link[upd[top - 1]] = avl_new_node(key, value); if (it->link[upd[top - 1]] == NULL) return -1; while (--top >= 0 && !done) { int lh, rh, max; cmp_res = ct_compare(KEY(up[top]), key); lh = height(up[top]->link[upd[top]]); rh = height(up[top]->link[!upd[top]]); if (lh - rh == 0) done = 1; if (lh - rh >= 2) { node_t *a = up[top]->link[upd[top]]->link[upd[top]]; node_t *b = up[top]->link[upd[top]]->link[!upd[top]]; if (height( a ) >= height( b )) up[top] = avl_single(up[top], !upd[top]); else up[top] = avl_double(up[top], !upd[top]); if (top != 0) up[top - 1]->link[upd[top - 1]] = up[top]; else root = up[0]; done = 1; } lh = height(up[top]->link[upd[top]]); rh = height(up[top]->link[!upd[top]]); max = avl_max(lh, rh); BALANCE(up[top]) = max + 1; } } (*rootaddr) = root; return 1; }
void *avl_remove(struct avl_tree *tree, void *key) { struct avl_node *it = tree->root; struct avl_node *up[AVL_MAX_HEIGHT]; int upd[AVL_MAX_HEIGHT], top = 0, cmp; paranoia(-500182, !it); // paranoia if not found // while ((cmp = memcmp(it->key, key, tree->key_size)) ) { while ((cmp = memcmp(it->key, key, tree->key_size)) || (it->link[0] && !memcmp(it->link[0]->key, key, tree->key_size))) { // Push direction and node onto stack upd[top] = (cmp < 0); up[top] = it; top++; if (!(it = it->link[(cmp < 0)])) return NULL; } // remember and return the found key. It might have been another one than intended key = it->key; // Remove the node: if (!(it->link[0] && it->link[1])) { // at least one child is NULL: // Which child is not null? int dir = !(it->link[0]); /* Fix parent */ if (top) { up[top - 1]->link[upd[top - 1]] = it->link[dir]; if (it->link[dir]) it->link[dir]->up = up[top - 1]; } else { tree->root = it->link[dir]; if (tree->root) tree->root->up = NULL; } debugFree(it, 1327); } else { // both childs NOT NULL: // Find the inorder successor struct avl_node *heir = it->link[1]; // Save the path upd[top] = 1; up[top] = it; top++; while (heir->link[0]) { upd[top] = 0; up[top] = heir; top++; heir = heir->link[0]; } // Swap data it->key = heir->key; // Unlink successor and fix parent up[top - 1]->link[ (up[top - 1] == it) ] = heir->link[1]; if ( heir->link[1]) heir->link[1]->up = up[top - 1]; debugFree(heir, 2327); } // Walk back up the search path while (--top >= 0) { int lh = avl_height(up[top]->link[upd[top]]); int rh = avl_height(up[top]->link[!upd[top]]); int max = avl_max(lh, rh); /* Update balance factors */ up[top]->balance = max + 1; // Terminate or re-balance as necessary: if (lh - rh >= 0) // re-balance upper path... continue; if (lh - rh == -1) // balance for upper path unchanged! break; if (!(up[top]) || !(up[top]->link[!upd[top]])) { dbgf(DBGL_SYS, DBGT_ERR, "up(top) %p link %p lh %d rh %d", (void*)(up[top]), (void*)((up[top]) ? (up[top]->link[!upd[top]]) : NULL), lh, rh); paranoia(-500187, (!(up[top]))); paranoia(-500188, (!(up[top]->link[!upd[top]]))); } /* paranoia(-500183, (lh - rh <= -3) ); paranoia(-500185, (lh - rh == 2) ); paranoia(-500186, (lh - rh >= 3) ); */ // if (lh - rh <= -2): rebalance here and upper path struct avl_node *a = up[top]->link[!upd[top]]->link[upd[top]]; struct avl_node *b = up[top]->link[!upd[top]]->link[!upd[top]]; if (avl_height(a) <= avl_height(b)) up[top] = avl_rotate_single(up[top], upd[top]); else up[top] = avl_rotate_double(up[top], upd[top]); // Fix parent: if (top) { up[top - 1]->link[upd[top - 1]] = up[top]; up[top]->up = up[top - 1]; } else { tree->root = up[0]; tree->root->up = NULL; } } return key; }
void avl_insert(struct avl_tree *tree, void *key) { if (tree->root) { struct avl_node *it = tree->root; struct avl_node *up[AVL_MAX_HEIGHT]; int upd[AVL_MAX_HEIGHT], top = 0; int done = 0; /* Search for an empty link, save the path */ for (;;) { /* Push direction and node onto stack */ // upd[top] = memcmp(it->key, key, tree->key_size) < 0; upd[top] = memcmp(it->key, key, tree->key_size) <= 0; up[top++] = it; if (it->link[upd[top - 1]] == NULL) break; it = it->link[upd[top - 1]]; } /* Insert a new node at the bottom of the tree */ it->link[upd[top - 1]] = avl_create_node(key); it->link[upd[top - 1]]->up = it; paranoia(-500178, (it->link[upd[top - 1]] == NULL)); /* Walk back up the search path */ while (--top >= 0 && !done) { int lh, rh, max; lh = avl_height(up[top]->link[upd[top]]); rh = avl_height(up[top]->link[!upd[top]]); /* Terminate or rebalance as necessary */ if (lh - rh == 0) done = 1; if (lh - rh >= 2) { struct avl_node *a = up[top]->link[upd[top]]->link[upd[top]]; struct avl_node *b = up[top]->link[upd[top]]->link[!upd[top]]; if (avl_height(a) >= avl_height(b)) up[top] = avl_rotate_single(up[top], !upd[top]); else up[top] = avl_rotate_double(up[top], !upd[top]); /* Fix parent */ if (top != 0) { up[top - 1]->link[upd[top - 1]] = up[top]; up[top]->up = up[top - 1]; } else { tree->root = up[0]; up[0]->up = NULL; } done = 1; } /* Update balance factors */ lh = avl_height(up[top]->link[upd[top]]); rh = avl_height(up[top]->link[!upd[top]]); max = avl_max(lh, rh); up[top]->balance = max + 1; } } else { tree->root = avl_create_node(key); paranoia( -500179, (tree->root==NULL)); } return; }