// ------------------------------------------------------------------------------ // Funcao rotacao dupla a direita // ------------------------------------------------------------------------------ nodo * rd_dir(nodo * x) { x->esq = rot_esq(x->esq); x = rot_dir(x); return x; }
// ------------------------------------------------------------------------------ // Funcao balanceamento // ------------------------------------------------------------------------------ nodo * balanceamento(nodo * raiz) { int fb = fat_bal(raiz); if ((fb <= -2) || (fb >=2)){ printf("-- Acao do Balanceamento: \n"); if (fb > 0){ fb = fat_bal(raiz->dir); if (fb >= 0){ printf(" rot simples a esq \n"); raiz = rot_esq(raiz); } else { printf(" rot dupla a esq.\n"); raiz = rd_esq(raiz); } } else { fb = fat_bal(raiz->esq); if (fb <= 0){ printf(" rot simples a dir\n"); raiz = rot_dir(raiz); } else { printf(" rot dupla a dir\n"); raiz = rd_dir(raiz); } } } return raiz; }
// ------------------------------------------------------------------------------ // Funcao rotacao dupla a esquerda // ------------------------------------------------------------------------------ nodo * rd_esq(nodo * x) { x->dir = rot_dir(x->dir); x = rot_esq(x); return x; }
//------------------------------------------------------------------------------ // ROT_ESQ_DIR // Realiza a rotação esquerda e direita de um nó //------------------------------------------------------------------------------ Registro *rot_esq_dir(Registro *no) { Registro *pai; Registro *no_esq; Registro *novo_no; pai = no->pai; no_esq = no->esq; no->esq = rot_esq(no_esq); no_esq = no->esq; novo_no = rot_dir(no); novo_no->pai = pai; return novo_no; }
//------------------------------------------------------------------------------ // ROT_DIR_ESQ // Realiza a rotação direita e esquerda de um nó //------------------------------------------------------------------------------ Registro *rot_dir_esq(Registro *no) { Registro *pai; Registro *no_dir; Registro *novo_no; pai = no->pai; no_dir = no->dir; no->dir = rot_dir(no_dir); no_dir = no->dir; novo_no = rot_esq(no); novo_no->pai = pai; return novo_no; }
//------------------------------------------------------------------------------ // 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 esquerda struct NO *balanceamento_esq(struct NO *no, bool h) { struct NO *fdir; int fbdir; switch (no->fb) { case 1: no->fb = 0; break; case 0: no->fb = -1; h = false; break; case -1: fdir = no->fdir; fbdir = fdir->fb; if (fbdir <= 0) { fdir = rot_esq(no); if (fbdir == 0) { no->fb = -1; fdir->fb = 1; h = false; } else { no->fb = 0; fdir->fb = 0; } no = fdir; } else { no = rot_dir_esq(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); }
struct NO *rot_dir_esq(struct NO *no) { rot_dir(no->fdir); return(rot_esq(no)); }
struct NO *rot_esq_dir(struct NO *no) { rot_esq(no->fesq); return(rot_dir(no)); }