//------------------------------------------------------------------------------ // REMOVE_AVL // Remove um registro e balanceia a árvore caso necessário //------------------------------------------------------------------------------ Registro *remove_avl(Registro *reg, const char *nome) { if (reg == NULL) return NULL; if (stricmp(reg->nome, nome) == 0) { if ((reg->esq) == NULL && (reg->dir == NULL)) { free(reg); return NULL; } if (reg->dir == NULL) { Registro *aux = reg->esq; free(reg); aux->fb = fator_bal(aux); return aux; } if (reg->esq == NULL) { Registro *aux = reg->dir; free(reg); aux->fb = fator_bal(aux); return aux; } Registro *aux = reg->esq; Registro *aux2 = reg->esq; for ( ; aux2->dir != NULL; aux2 = aux2->dir); aux2->dir=reg->dir; free(reg); aux->fb=fator_bal(aux); if (aux->fb >= 2) { if (aux->dir->dir != NULL) aux=rot_esq(aux); else rot_dir_esq(aux); aux->fb = fator_bal(aux); } if (aux->fb <= -2) { if (aux->esq->esq != NULL) aux = rot_dir(reg); else rot_esq_dir(aux); aux->fb = fator_bal(aux); } return aux; } if (stricmp(reg->nome, nome) > 0) reg->esq = remove_avl(reg->esq, nome); if (stricmp(reg->nome, nome) < 0) reg->dir = remove_avl(reg->dir, nome); return reg; }
//------------------------------------------------------------------------------ // REG_INSERE_AVL // Insere um novo registro, preenchendo os dados e o colocando em sua // posição correta dentro da árvore binária e checa o balanceamento da // mesma. Caso esteje balanceada, reorganiza os nós. //------------------------------------------------------------------------------ Registro *reg_insere_avl(Registro *reg, const char *nome, const char *curso, const char *turno, const char *cidade) { if (reg == NULL) { reg = reg_cria(); strcpy(reg->nome , nome); strcpy(reg->curso , curso); strcpy(reg->turno , turno); strcpy(reg->cidade, cidade); reg->fb = 0; } if (strcmp(reg->nome, nome) > 0) { Registro *aux = reg_insere_avl(reg->esq, nome, curso, turno, cidade); reg->esq = aux; reg->esq->pai = reg; } if (strcmp(reg->nome, nome) < 0) { Registro *aux = reg_insere_avl(reg->dir, nome, curso, turno, cidade); reg->dir = aux; reg->dir->pai = reg; } reg->fb = fator_bal(reg); if (reg->fb >= 2) { if (reg->dir->dir != NULL) reg=rot_esq(reg); else reg = rot_dir_esq(reg); reg->fb = fator_bal(reg); } if (reg->fb <= -2) { if (reg->esq->esq != NULL) reg = rot_dir(reg); else reg = rot_esq_dir(reg); reg->fb = fator_bal(reg); } return reg; }
// atualização do FB e balanceamento para a raiz direita struct NO *balanceamento_dir(struct NO *no, bool h) { struct NO *fesq; int fbesq; switch (no->fb) { case -1: no->fb = 0; break; case 0: no->fb = 1; h = false; break; case 1: fesq = no->fesq; fbesq = fesq->fb; if (fbesq >= 0) { fesq = rot_dir(no); if (fbesq == 0) { no->fb = 1; fesq->fb = -1; h = false; } else { no->fb = 0; fesq->fb = 0; } no = fesq; } else { no = rot_esq_dir(no); no->fb = 0; } } return(no); }
struct NO *inserir_arvore_avl_aux(struct NO *raiz, struct INFO info, int *atual_fb) { if (raiz == NULL) { raiz = (struct NO *) malloc(sizeof(struct NO)); raiz->fesq = raiz->fdir = raiz->pai = NULL; raiz->info = info; raiz->fb = 0; *atual_fb = 1; } else { if (raiz->info.chave > info.chave) { //desce pela esquerda raiz->fesq = inserir_arvore_avl_aux(raiz->fesq, info, atual_fb); raiz->fesq->pai = raiz; if (*atual_fb) { switch(raiz->fb) { case -1: { raiz->fb = 0; *atual_fb = 0; break; } case 0: { raiz->fb = 1; break; } case 1: { if (raiz->fesq->fb == 1) { raiz = rot_dir(raiz); raiz->fb = 0; raiz->fdir->fb = 0; *atual_fb = 0; } else { raiz = rot_esq_dir(raiz); if (raiz->fb == 1) { raiz->fesq->fb = 0; raiz->fb = -1; } else { raiz->fesq->fb = 1; raiz->fdir->fb = 0; } raiz->fb = 0; *atual_fb = 0; } break; } } } } else { //desce pela direita raiz->fdir = inserir_arvore_avl_aux(raiz->fdir, info, atual_fb); raiz->fdir->pai = raiz; if (*atual_fb) { switch(raiz->fb) { case 1: { raiz->fb = 0; *atual_fb = 0; break; } case 0: { raiz->fb = -1; break; } case -1: { if (raiz->fdir->fb == -1) { raiz = rot_esq(raiz); raiz->fb = 0; raiz->fesq->fb = 0; *atual_fb = 0; } else { raiz = rot_dir_esq(raiz); if (raiz->fb == -1) { raiz->fdir->fb = 0; raiz->fb = 1; } else { raiz->fdir->fb = -1; raiz->fesq->fb = 0; } raiz->fb = 0; *atual_fb = 0; } break; } } } } } return(raiz); }