Árvore binária AVL
Publicado por Caio Dutra (última atualização em 23/01/2010)
[ Hits: 47.781 ]
Está aí a estrutura de uma árvore AVL.
Abraço!
/* ---------------------------------------------------------------- avl_tree.h
AVL Tree - Caio Dutra <caiodutra@uft.edu.br>
UFT - EDII - 01/2010
Biblioteca relativa a estrutura de dados. Caracteriza aqui a Árvore AVL.
----> Por convenção, todos as funções listadas neste arquivo referentes a
manipulação de árvore AVL terão o prefixo avl_, para evitar possíveis
conflitos de nomes.
---------------------------------------------------------------------------*/
#ifndef AVL_H
#define AVL_H
#ifdef __cplusplus
exterm "C" {
#endif
typedef struct AVL_Node
{
/*
* Estrutura do nó da árvore AVL.
* Contém um bit extra que informa
* o grau de balanceamento da árvore.
* Se for 0, 1 ou -1, a árvore está
* balanceada. Se não, serão realizadas
* algumas mudanças até que se balanceie
*/
void *info; // Informação contida no nó
int bal; // Fator de balanceamento do nó
struct AVL_Node *pai; // Aponta para o nó ancestral
struct AVL_Node *esq; // Aponta para o filho da esquerda
struct AVL_Node *dir; // Aponta para o filho da direita
} AVL_Node;
typedef struct AVL_Tree
{
/*
* Estrutura que define a árvore AVL.
* Aonde está guardada a raiz da árvore.
* Contém ponteiros para funções que
* manipulam as informações contidas na
* árvore.
*
* A função que o ponteiro compara_info
* aponta deverá retornar um valor inteiro
* segundo a seguinte legenda:
* +1 => Se o primeiro for maior
* -1 => Se o segundo for maior
* 0 => Se os dois forem iguais
*/
AVL_Node *root; // Raiz da árvore
unsigned int num_nodes; // Número de nós da árvore
// Função que compara duas informações
int (*compara_info)( const void *, const void * );
// Função que imprime uma informação
void (*imprime_info)( const void * );
} AVL_Tree;
/* Funções para manipulação da árvore */
// Inicialização da árvore
void avl_init ( AVL_Tree **, int (*compara_info)( const void *, const void * ),
void (*imprime_info)( const void * ));
// Insere um elemento na árvore
int avl_insert ( AVL_Tree **, AVL_Node *, AVL_Node **, void * );
// Remove um elemento da árvore
int avl_remove ( AVL_Tree **, AVL_Node **, void * );
// Realiza o percurso em pré-ordem
void avl_walk_pre ( AVL_Tree *, AVL_Node * );
// Realiza o percurso em pos-ordem
void avl_walk_pos ( AVL_Tree *, AVL_Node * );
// Realiza o percurso em ordem simetrica
void avl_walk_sim ( AVL_Tree *, AVL_Node * );
// Realiza o percurso na árvore por nível
void avl_walk_byLevel ( AVL_Tree * );
// Faz uma busca na árvore
AVL_Node *avl_search ( AVL_Tree *, AVL_Node *, void * );
// Retorna a altura de uma sub-árvore
int avl_height ( AVL_Node * );
#ifdef __cplusplus
}
#endif
#endif /* AVL_H */
/* ---------------------------------------------------------------- avl_tree.c
AVL Tree API - Caio Dutra <caiodutra@uft.edu.br>
UFT - EDII - 01/2010
Biblioteca relativa a estrutura de dados. Caracteriza aqui a Árvore AVL.
----> Por convenção, todos as funções listadas neste arquivo referentes a
manipulação de árvore AVL terão o prefixo avl_, para evitar possíveis
conflitos de nomes.
---------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include "avl_tree.h"
void avl_init ( AVL_Tree **tree,
int (*compara_info)( const void *, const void *),
void (*imprime_info)( const void * ))
/* Inicializa a árvore */
{
AVL_Tree *nova;
nova = ( AVL_Tree * ) malloc ( sizeof ( AVL_Tree ));
if ( nova == NULL ) return;
nova->root = NULL;
nova->num_nodes = 0;
nova->compara_info = compara_info;
nova->imprime_info = imprime_info;
*tree = nova;
}
int avl_height ( AVL_Node *node ) {
int esq, dir;
if ( node == NULL ) return -1;
esq = avl_height ( node->esq );
dir = avl_height ( node->dir );
if ( esq > dir )
return esq + 1;
else
return dir + 1;
}
/* -- Rotações de sub-árvore --
*
* A árvore AVL necessita, além das rotinas
* básicas, algumas rotinas auxiliares para
* mantê-la balanceada. São elas: rotação
* simples para a esquerda, rotação simples
* para a direita.
*/
AVL_Node *rotacao_direita ( AVL_Node *p )
/* Rotação simples para a direita */
{
AVL_Node *q;
q = p->esq;
//----------------> Realiza a rotação
p->esq = q->dir;
if ( q->dir != NULL )
q->dir->pai = p;
q->dir = p;
q->pai = p->pai;
if ( p->pai != NULL )
if ( p->pai->esq == p )
p->pai->esq = q;
else
p->pai->dir = q;
p->pai = q;
//----------------> Rebalanceia
q->bal = avl_height ( q->dir ) - avl_height ( q->esq );
p->bal = avl_height ( p->dir ) - avl_height ( p->esq );
return q;
}
AVL_Node *rotacao_esquerda ( AVL_Node *p )
/* Rotação simples para a esquerda */
{
AVL_Node *q;
q = p->dir;
//----------------> Realiza a rotação
p->dir = q->esq;
if ( q->esq != NULL )
q->esq->pai = p;
q->esq = p;
q->pai = p->pai;
if ( p->pai != NULL )
if ( p->pai->esq == p )
p->pai->esq = q;
else
p->pai->dir = q;
p->pai = q;
//----------------> Rebalanceia
q->bal = avl_height ( q->dir ) - avl_height ( q->esq );
p->bal = avl_height ( p->dir ) - avl_height ( p->esq );
return q;
}
/* Inserção na árvore AVL */
int avl_insert ( AVL_Tree **tree, AVL_Node *pai, AVL_Node **node, void *info )
{
AVL_Node *novo;
int aux;
if ( *tree == NULL ) return -1;
if ( *node == NULL )
// Se for o local correto para a inserção
{
novo = ( AVL_Node * ) malloc ( sizeof ( AVL_Node ));
if ( novo == NULL ) return -1;
novo->info = info;
novo->bal = 0;
novo->pai = pai;
novo->esq = NULL;
novo->dir = NULL;
*node = novo;
(*tree)->num_nodes++;
return 1;
}
/*
* Procura o local apropriado. Na volta da pilha do processador, o
* algoritmo vai atualizando o fator de balanceamento de cada nó.
* São feitas rotações, se necessárias, para que a árvore se rebalanceie.
*/
if ( (*tree)->compara_info( info, (*node)->info ) == +1 ) {
aux = avl_insert ( tree, *node, &((*node)->dir), info );
if ( aux != 1 ) return 0;
if ( ++((*node)->bal) == 2 ) {
if ( (*node)->dir->bal == 1 ) {
*node = rotacao_esquerda ( *node );
return 0;
}
(*node)->dir = rotacao_direita ( (*node)->dir );
*node = rotacao_esquerda ( *node );
return 0;
}
return ( (*node)->bal == 0 )? 0: 1;
}
if ( (*tree)->compara_info( info, (*node)->info ) == -1 ) {
aux = avl_insert ( tree, *node, &((*node)->esq), info );
if ( aux != 1 ) return 0;
if ( --((*node)->bal) == -2 ) {
if ( (*node)->esq->bal == -1 ) {
*node = rotacao_direita ( *node );
return 0;
}
(*node)->esq = rotacao_esquerda ( (*node)->esq );
*node = rotacao_direita ( *node );
return 0;
}
return ( (*node)->bal == 0 )? 0: 1;
}
return 0;
}
/* Remove um elemento da árvore */
int avl_remove ( AVL_Tree **tree, AVL_Node **node, void *info )
{
int ret;
if ( *node == NULL || *tree == NULL ) return -1;
if ( (*tree)->compara_info( info, (*node)->info ) == +1 )
// Vai para a S.A. da esquerda
{
ret = avl_remove ( tree, &((*node)->dir), info );
if ( ret != 1 ) return 0;
if ( --((*node)->bal) == -2 ) {
if ( (*node)->esq->bal == -1 ) {
*node = rotacao_direita ( *node );
return 0;
}
(*node)->esq = rotacao_esquerda ( (*node)->esq );
*node = rotacao_direita ( *node );
return 0;
}
return ( (*node)->bal == 0 )? 1: 0;
}
if ( (*tree)->compara_info( info, (*node)->info ) == -1 )
// Vai para a S.A. da direita
{
ret = avl_remove ( tree, &((*node)->esq), info );
if ( ret != 1 ) return 0;
if ( ++((*node)->bal) == +2 ) {
if ( (*node)->dir->bal == 1 ) {
*node = rotacao_esquerda ( *node );
return 0;
}
(*node)->dir = rotacao_direita ( (*node)->dir );
*node = rotacao_esquerda ( *node );
return 0;
}
return ( (*node)->bal == 0 )? 1: 0;
}
if ( (*tree)->compara_info( info, (*node)->info ) == 0 )
// Encontrou o elemento a ser removido
{
AVL_Node *aux, *temp;
void *i;
if ( (*node)->esq == NULL ) {
if ( (*node)->dir == NULL )
// Se não contiver filho algum
{
free ( *node );
*node = NULL;
(*tree)->num_nodes--;
return 1;
}
// Se contiver o filho da direita
aux = *node;
temp = (*node)->dir;
temp->pai = (*node)->pai;
if ( (*node)->pai != NULL )
if ( (*node)->pai->esq == *node )
(*node)->pai->esq = temp;
else
(*node)->pai->dir = temp;
*node = temp;
free ( aux );
(*tree)->num_nodes--;
return 1;
}
if ( (*node)->dir == NULL )
// Se contiver apenas o filho da esquerda
{
aux = *node;
temp = (*node)->esq;
temp->pai = (*node)->pai;
if ( (*node)->pai != NULL )
if ( (*node)->pai->esq == *node )
(*node)->pai->esq = temp;
else
(*node)->pai->dir = temp;
*node = temp;
free ( aux );
(*tree)->num_nodes--;
return 1;
}
// Se contiver os dois filhos
aux = (*node)->esq;
while ( aux->dir != NULL )
aux = aux->dir;
i = aux->info;
avl_remove ( tree, node, aux->info );
(*node)->info = i;
return 1;
}
}
/* Percursos da árvore */
void avl_walk_pre ( AVL_Tree *tree, AVL_Node *node )
// Percorre a árvore em pré-ordem
{
if ( node == NULL ) return;
tree->imprime_info( node->info );
if ( node->esq != NULL && node->dir != NULL ) printf ( ", " );
avl_walk_pre ( tree, node->esq );
avl_walk_pre ( tree, node->dir );
}
void avl_walk_pos ( AVL_Tree *tree, AVL_Node *node )
// Percorre a árvore em pós-ordem
{
if ( node == NULL ) return;
avl_walk_pre ( tree, node->esq );
avl_walk_pre ( tree, node->dir );
tree->imprime_info( node->info );
if ( node->esq != NULL && node->dir != NULL ) printf ( ", " );
}
void avl_walk_sim ( AVL_Tree *tree, AVL_Node *node )
// Percorre a árvore em ordem simétrica
{
if ( node == NULL ) return;
avl_walk_pre ( tree, node->esq );
tree->imprime_info( node->info );
if ( node->esq != NULL && node->dir != NULL ) printf ( ", " );
avl_walk_pre ( tree, node->dir );
}
void avl_walk_lev ( AVL_Tree *tree )
// Percorre a árvore por nível ( Busca Lateral )
{
AVL_Node *queue[tree->num_nodes];
AVL_Node *aux;
int tail = -1, i;
if ( tree->root == NULL ) return;
queue[++tail] = tree->root;
while ( tail > -1 ) {
aux = queue[0];
for ( i = 0; i < tail; i++ )
queue[i] = queue[i+1];
tail--;
tree->imprime_info( aux->info );
printf ( " " );
if ( aux->esq != NULL )
queue[++tail] = aux->esq;
if ( aux->dir != NULL )
queue[++tail] = aux->dir;
}
}
void avl_print ( AVL_Tree *tree, AVL_Node *node, int level )
{
int i;
if ( tree == NULL || node == NULL ) return;
for ( i = 0; i < level; i++ )
printf ( " " );
printf ( "> [" );
tree->imprime_info( node->info );
printf ( "][%i]\n", node->bal );
avl_print ( tree, node->esq, level + 1 );
avl_print ( tree, node->dir, level + 1 );
}
/* Busca por um elemento */
AVL_Node *avl_search ( AVL_Tree *tree, AVL_Node *node, void *info )
{
if ( tree == NULL || node == NULL ) return NULL;
if ( tree->compara_info( info, node->info ) == 0 ) return node;
if ( tree->compara_info( info, node->info ) > 0 )
return avl_search ( tree, node->dir, info );
else
return avl_search ( tree, node->esq, info );
}
Dangerous Tux Game com gráficos
1o. joguinho Labirinto (com graficos).c
Rotina para controle de portas paralelas em C. (biblioteca LP.h)
Cirurgia para acelerar o openSUSE em HD externo via USB
Void Server como Domain Control
Modo Simples de Baixar e Usar o bash-completion
Monitorando o Preço do Bitcoin ou sua Cripto Favorita em Tempo Real com um Widget Flutuante
[Resolvido] VirtualBox can't enable the AMD-V extension
Como verificar a saúde dos discos no Linux
Como instalar , particionar, formatar e montar um HD adicional no Linux?
Como automatizar sua instalação do Ubuntu para desenvolvimento de software.
Quais os códigos mais dificeis que vcs sabem fazer? (3)
Fiz uma pergunta no fórum mas não consigo localizar (14)
Upscaling com imagem cortada no monitor secundário ao usar iGPU Multi ... (1)
Não consigo instalar distro antiga no virtualbox nem direto no hd (7)
Servidor Ubuntu 24.04 HD 500 não tenho espaço na \home\adminis... [RES... (8)









