static inline void avl_rep_height (node* tree) { unsigned char max_height = (avl_height (tree -> child [left]) > avl_height (tree -> child [right])) ? avl_height (tree -> child [left]) : avl_height (tree -> child [right]); tree -> height = max_height + 1; }
static avl_node *critical_node(avl_node * added, int *pos1, int *pos2, const avl_node * prec) { int fdb = 0; if (added == NULL) return NULL; if (prec == NULL) *pos1 = *pos2 = 0; else { *pos2 = *pos1; if (prec == added->left_child) *pos1 = AVL_S; else *pos1 = AVL_D; /* prec == added->right_child */ } fdb = abs(avl_height(added->left_child) - avl_height(added->right_child)); if (fdb > 1) return added; else { prec = added; return critical_node(added->father, pos1, pos2, prec); } }
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 int avl_height(const avl_tree root) { if (root == NULL) return -1; else { int tmp1 = avl_height(root->left_child); int tmp2 = avl_height(root->right_child); return (1 + ((tmp1 > tmp2) ? tmp1 : tmp2)); } }
void test_diverse(){ int i; struct node_avl * p = NULL; DESCRIBE("Teste de diferentes balanceamentos"); for(i=1; i<=8; i++){ struct node_avl * new_root = avl_insert(p,i); isNotNull(new_root); p = new_root; } THEN("Altura da árvore deve ser 3"); isEqual(avl_height(p),1); DESCRIBE("Remove 5 e 1"); p = avl_delete(p,5); p = avl_delete(p,1); THEN("Altura deve ser 2"); isEqual(avl_height(p),1); DESCRIBE("Remove 8 e 7"); p = avl_delete(p,8); p = avl_delete(p,7); THEN("Altura deve ser 2"); isEqual(avl_height(p),0); DESCRIBE("Remove 3 (raiz)"); p = avl_delete(p,3); THEN("Altura deve ser 1"); isEqual(avl_height(p),0); DESCRIBE("Remove 2, 4 e 6"); p = avl_delete(p,2); p = avl_delete(p,4); p = avl_delete(p,6); THEN("Altura deve ser 0"); isEqual(avl_height(p),0); }
void test_insert(){ int i; struct node_avl * p = NULL; DESCRIBE("INSERE ELEMENTOS"); WHEN("Eu insiro elementos"); IF("Insiro um número razoável MAX"); THEN("Deve inserir todos"); for(i=1; i<=MAX; i++){ struct node_avl * new_root = avl_insert(p,i); isNotNull(new_root); p = new_root; } THEN("Deve não estar vazia"); isNotEqual(avl_height(p),0); THEN("Deve encontrar todas as chaves inseridas"); for(i=1; i<=MAX; i++){ isNotNull(avl_search(p,i)); } THEN("Alturas da subárvore direita e esquerda não podem ter diferença maior que 1"); if (p){ int left, right, diff; left = avl_height(p->left); right = avl_height(p->right); diff = left>right?left-right:right-left; diff = diff>1? 0:1; isNotEqual(diff,0); } else isNotNull(NULL); THEN("Consegue imprimir INFIX"); avl_print_infix(p); avl_destroy(p); }
void test_create(){ DESCRIBE("CRIA ARVORE"); WHEN("Eu crio uma ARVORE"); IF("Uma chave"); THEN("Resultado deve ser ponteiro"); struct node_avl * p = avl_insert(NULL,1); isNotNull(p); THEN("Deve ter altura 1"); isEqual(avl_height(p),1); avl_destroy(p); }
void avl_bfs_dump(struct avl *avl, dump dmp) { struct avl_node *node = avl->root; struct linklist *list; int depth = 0, idx = 0, tmp = 0; int pre_depth = -1, pre_idx_line = -1; int height = avl_height(avl); if (!node) return; if ((list = linklist_new()) == NULL) return; if (linklist_insert(list, node, (void *) (long int) depth, NULL)) goto fail; while (linklist_size(list) > 0) { node = (struct avl_node *) linklist_remove_head(list, (void **) &depth, (void **) &tmp); if (node) _node_bfs_dump(node->value, depth, idx, height, dmp, &pre_depth, &pre_idx_line); if (linklist_insert(list, node ? node->left : NULL, (void *) (long int) (depth + 1), NULL)) goto fail; if (linklist_insert(list, node ? node->right : NULL, (void *) (long int) (depth + 1), NULL)) goto fail; if (idx + 1 == (int) pow(2, height + 1)) break; idx++; } printf("\n"); fail: linklist_delete(list); }
static inline int avl_bal_fact (node* tree) { return avl_height (tree -> child [left]) - avl_height (tree -> child [right]); }
int main(int argc, char *argv[]) { avl_tree *ptree; avl_tree *itree; avl_tree *mtree; avl_node *lookup = (avl_node*)0x1; struct timeval start, finish; int i, x; printf("\nP-TREE:\n"); for (i = 0; i < NNN; i++) ndata[i] = i; for (i = 0; i < MMM; i++) mdata[i] = i; ptree = avl_init(int_compare, NULL, 0); gettimeofday(&start, NULL); for (i = 0; i < MMM; i++) avl_insert(ptree, &mdata[i], NULL); //for (i = NNN; i > 0; i--) avl_insert(ptree, &ndata[i], NULL); gettimeofday(&finish, NULL); printf("INSERT: n = %7d h = %2d v = %d (%d sec %u msec)\n", avl_size(ptree), avl_height(ptree), avl_validate(ptree, ptree->root, NULL), (int) (finish.tv_sec - start.tv_sec ), (unsigned int)(finish.tv_usec - start.tv_usec)/1000); gettimeofday(&start, NULL); for (i = 0; i < MMM && lookup; i++) lookup = avl_lookup(ptree, &mdata[i], NULL); gettimeofday(&finish, NULL); printf("LOOKUP: n = %7d h = %2d v = %d (%d sec %u msec)\n", i, avl_height(ptree), avl_validate(ptree, ptree->root, NULL), (int) (finish.tv_sec - start.tv_sec ), (unsigned int)(finish.tv_usec - start.tv_usec)/1000); gettimeofday(&start, NULL); for (i = NNN - 1; i >= 0; i--) { avl_remove(ptree, &ndata[i], NULL); } #if 0 for (i = 0, srand(time(NULL)); i < NNN;) { x = rand() % NNN; if (avl_lookup(ptree, &ndata[x], NULL)) { avl_remove(ptree, &ndata[x], NULL); assert(avl_validate(ptree, ptree->root, NULL)); i++; } } #endif gettimeofday(&finish, NULL); printf("REMOVE: n = %7d h = %2d v = %d (%d sec %u msec)\n", avl_size(ptree), avl_height(ptree), avl_validate(ptree, ptree->root, NULL), (int) (finish.tv_sec - start.tv_sec ), (unsigned int)(finish.tv_usec - start.tv_usec)/1000); gettimeofday(&start, NULL); avl_free(ptree); gettimeofday(&finish, NULL); printf("DSTROY: n = %7d h = %2d v = %d (%d sec %u msec)\n", 0, 0, 1, (int) (finish.tv_sec - start.tv_sec ), (unsigned int)(finish.tv_usec - start.tv_usec)/1000); printf("\nI-TREE:\n"); memset(nintr, 0, NNN * sizeof(intr)); memset(mintr, 0, MMM * sizeof(intr)); for (i = 0; i < NNN; i++) nintr[i].data = i; for (i = 0; i < MMM; i++) mintr[i].data = i; itree = avl_init(intr_compare, NULL, AVL_TREE_INTRUSIVE); gettimeofday(&start, NULL); for (i = 0; i < MMM; i++) avl_insert(itree, &mintr[i], NULL); //for (i = NNN - 1; i >= 0; i--) avl_insert(itree, &nintr[i], NULL); gettimeofday(&finish, NULL); printf("INSERT: n = %7d h = %2d v = %d (%d sec %u msec)\n", avl_size(itree), avl_height(itree), avl_validate(itree, itree->root, NULL), (int) (finish.tv_sec - start.tv_sec ), (unsigned int)(finish.tv_usec - start.tv_usec)/1000); gettimeofday(&start, NULL); for (i = 0; i < MMM && lookup; i++) lookup = avl_lookup(itree, &mintr[i], NULL); gettimeofday(&finish, NULL); printf("LOOKUP: n = %7d h = %2d v = %d (%d sec %u msec)\n", i, avl_height(itree), avl_validate(itree, itree->root, NULL), (int) (finish.tv_sec - start.tv_sec ), (unsigned int)(finish.tv_usec - start.tv_usec)/1000); gettimeofday(&start, NULL); for (i = NNN - 1; i >= 0; i--) { avl_remove(itree, &nintr[i], NULL); } #if 0 for (i = 0, srand(time(NULL)); i < NNN;) { x = rand() % NNN; if (avl_lookup(itree, &nintr[x], NULL)) { avl_remove(itree, &nintr[x], NULL); assert(avl_validate(itree, itree->root, NULL)); i++; } } #endif gettimeofday(&finish, NULL); printf("REMOVE: n = %7d h = %2d v = %d (%d sec %u msec)\n", avl_size(itree), avl_height(itree), avl_validate(itree, itree->root, NULL), (int) (finish.tv_sec - start.tv_sec ), (unsigned int)(finish.tv_usec - start.tv_usec)/1000); gettimeofday(&start, NULL); avl_free(itree); gettimeofday(&finish, NULL); printf("DSTROY: n = %7d h = %2d v = %d (%d sec %u msec)\n\n", 0, 0, 1, (int) (finish.tv_sec - start.tv_sec ), (unsigned int)(finish.tv_usec - start.tv_usec)/1000); printf("\nM-TREE:\n"); memset(nmulti, 0, NNN * sizeof(multi)); memset(mmulti, 0, MMM * sizeof(multi)); for (i = 0; i < NNN; i++) {nmulti[i].key[0] = i;nmulti[i].key[1] = i+1;} for (i = 0; i < MMM; i++) {mmulti[i].key[0] = i;mmulti[i].key[1] = i+1;} avl_compare_fn comps[2] = { multi_comp_0, multi_comp_1 }; mtree = avl_multi_init(comps, NULL, 2, AVL_TREE_INTRUSIVE); gettimeofday(&start, NULL); for (i = 0; i < MMM; i++) avl_multi_insert(mtree, &mmulti[i], NULL); //for (i = NNN - 1; i >= 0; i--) avl_multi_insert(mtree, &nmulti[i], NULL); gettimeofday(&finish, NULL); printf("INSERT: n = %7d h = %2d v = %d (%d sec %u msec)\n", avl_size(mtree), avl_height(mtree), avl_validate(mtree, mtree->root, NULL) && avl_validate(&mtree[0], mtree[0].root, NULL) == avl_validate(&mtree[1], mtree[1].root, NULL) , (int) (finish.tv_sec - start.tv_sec ), (unsigned int)(finish.tv_usec - start.tv_usec)/1000); gettimeofday(&start, NULL); for (i = 0; i < MMM && lookup; i++) lookup = avl_lookup(mtree, &mmulti[i], NULL); gettimeofday(&finish, NULL); printf("LOOKUP: n = %7d h = %2d v = %d (%d sec %u msec)\n", avl_size(mtree), avl_height(mtree), avl_validate(mtree, mtree->root, NULL) && avl_validate(&mtree[0], mtree[0].root, NULL) == avl_validate(&mtree[1], mtree[1].root, NULL) , (int) (finish.tv_sec - start.tv_sec ), (unsigned int)(finish.tv_usec - start.tv_usec)/1000); gettimeofday(&start, NULL); //avl_walk(&mtree[0], multi_print_0, NULL, 0); printf("---\n");fflush(stdout); //avl_walk(&mtree[1], multi_print_1, NULL, 0); printf("===\n");fflush(stdout); for (i = MMM - 1; i >= 1000; i--) { avl_multi_remove(mtree, &mmulti[i], NULL); } //avl_walk(&mtree[0], multi_print_0, NULL, 0); printf("---\n");fflush(stdout); //avl_walk(&mtree[1], multi_print_1, NULL, 0); printf("===\n");fflush(stdout); #if 0 for (i = 0, srand(time(NULL)); i < NNN;) { x = rand() % NNN; if (avl_lookup(itree, &nintr[x], NULL)) { avl_remove(itree, &nintr[x], NULL); assert(avl_validate(itree, itree->root, NULL)); i++; } } #endif gettimeofday(&finish, NULL); printf("REMOVE: n = %7d h = %2d v = %d (%d sec %u msec)\n", avl_size(mtree), avl_height(mtree), avl_validate(mtree, mtree->root, NULL) && avl_validate(&mtree[0], mtree[0].root, NULL) == avl_validate(&mtree[1], mtree[1].root, NULL) , (int) (finish.tv_sec - start.tv_sec ), (unsigned int)(finish.tv_usec - start.tv_usec)/1000); gettimeofday(&start, NULL); avl_free(mtree); gettimeofday(&finish, NULL); printf("DSTROY: n = %7d h = %2d v = %d (%d sec %u msec)\n\n", 0, 0, 1, (int) (finish.tv_sec - start.tv_sec ), (unsigned int)(finish.tv_usec - start.tv_usec)/1000); return 0; }
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; }