Lista de Exercícios — Árvores Binárias de Busca (ABB)¶
Foco: Inserção, Busca, Remoção e Propriedades de Ordenação¶
Atenção
Esta lista assume a propriedade de Árvore Binária de Busca:
Para todo nó N, todos os valores na subárvore esquerda são menores que N->valor, e todos os valores na subárvore direita são maiores que N->valor.
Valores duplicados não são permitidos nesta lista.
📋 Convenções e Pré-requisitos¶
Estrutura de Dados¶
Funções Auxiliares Disponibilizadas¶
// Cria um novo nó com o valor informado e filhos especificados
Arvore* criar_arvore(int valor, Arvore* esq, Arvore* dir);
// Libera toda a memória da árvore (pós-ordem)
void liberar_arvore(Arvore* raiz);
// Percursos básicos (já implementados)
void pre_ordem(Arvore* raiz);
void em_ordem(Arvore* raiz); // Em ABB: retorna valores em ordem crescente!
void pos_ordem(Arvore* raiz);
Regras Gerais¶
- Todas as funções devem ser recursivas, salvo indicação contrária.
- Árvores vazias são representadas por
NULL. - Use
intpara valores e retornos lógicos (1= verdadeiro,0= falso). - Não modifique a estrutura em funções de consulta (busca, validação, etc.).
- Em funções de modificação (inserção, remoção), retorne a nova raiz se necessário.
🔹 Nível 1: Compreensão da Propriedade ABB¶
Exercício 1 — Identificação Visual¶
Para cada árvore abaixo, indique se é ou não uma ABB válida. Justifique brevemente.
Exercício 2 — Previsão de em_ordem¶
Considere a ABB abaixo:
a) Qual sequência será impressa por em_ordem(raiz)?
b) Por que essa propriedade é útil em ABBs?
Exercício 3 — Montagem por Inserção Sequencial¶
Dada a sequência de inserções: 50, 30, 70, 20, 40, 60, 80
a) Desenhe a ABB resultante, inserindo um valor por vez na ordem dada.
b) Escreva o código C que monta essa árvore usando apenas inserir_abr() (função do Exercício 4).
🔹 Nível 2: Operações Fundamentais de ABB¶
Exercício 4 — Inserção em ABB¶
Implemente:
Insere valor na ABB mantendo a propriedade de busca.
Retorna a raiz da árvore (pode mudar apenas na primeira inserção).
Dica recursiva
- Se
raiz == NULL: crie e retorne novo nó - Se
valor < raiz->valor: insira à esquerda - Se
valor > raiz->valor: insira à direita - Se igual: ignore (sem duplicatas)
Exercício 5 — Busca em ABB¶
Implemente:
Retorna ponteiro para o nó com alvo, ou NULL se não existir.
Aproveite a propriedade ABB para não percorrer toda a árvore.
Exercício 6 — Menor e Maior Valor¶
Implemente:
int minimo_abr(Arvore* raiz); // Assume árvore não-vazia
int maximo_abr(Arvore* raiz); // Assume árvore não-vazia
Dica: o mínimo está sempre no nó mais à esquerda; o máximo, no mais à direita.
Exercício 7 — Validação de ABB¶
Implemente:
Retorna 1 se a árvore satisfaz a propriedade de busca, 0 caso contrário.
Cuidado
Não basta verificar esq->valor < raiz->valor < dir->valor.
Todos os valores da subárvore esquerda devem ser menores que a raiz, e todos da direita, maiores.
Dica: Use uma função auxiliar com limites:
int eh_abr_aux(Arvore* raiz, int min, int max);
🔹 Nível 3: Remoção e Operações Avançadas¶
Exercício 8 — Remoção em ABB¶
Implemente:
Remove o nó com valor da ABB, mantendo a propriedade de busca.
Retorna a nova raiz da árvore.
Casos a considerar
- Nó não encontrado → retorna
raiz - Nó é folha → libera e retorna
NULL - Nó tem um filho → retorna o filho no lugar
- Nó tem dois filhos → substitua pelo sucessor (menor da subárvore direita) ou pelo antecessor (maior da subárvore esquerda), e remova recursivamente esse substituto.
Exercício 9 — Sucessor e Antecessor¶
Implemente:
Arvore* sucessor_abr(Arvore* raiz, int valor); // Retorna nó com o sucessor de 'valor'
Arvore* antecessor_abr(Arvore* raiz, int valor); // Retorna nó com o antecessor de 'valor'
- Sucessor: menor valor maior que
valorna árvore - Antecessor: maior valor menor que
valorna árvore - Retorna
NULLse não existir.
Dica: use busca em ABB + lógica de "último candidato válido".
Exercício 10 — Contagem de Nós em Intervalo¶
Implemente:
Retorna quantos nós possuem valores min <= valor <= max.
Otimização ABB
Se raiz->valor < min, não percorra a esquerda.
Se raiz->valor > max, não percorra a direita.
🔹 Nível 4: Desafios e Aplicações¶
Exercício 11 — Altura Mínima e Máxima de ABB¶
Dado n valores distintos inseridos em uma ABB:
a) Qual é a altura mínima possível? (desenhe um exemplo para n=7)
b) Qual é a altura máxima possível? (desenhe um exemplo para n=7)
c) Implemente:
Exercício 12 — Construção de ABB Balanceada a Partir de Vetor Ordenado¶
Implemente:
Dado um vetor já ordenado, construa uma ABB com altura mínima (balanceada).
Estratégia: escolha o elemento do meio como raiz, recursivamente construa esquerda e direita.
Exercício 13 — Verificação de Subárvore ABB¶
Implemente:
Retorna 1 se sub é uma subárvore válida de raiz (mesma estrutura e valores), considerando propriedades de ABB.
Exercício 14 — Impressão por Níveis (BFS) em ABB¶
Implemente:
Imprime os valores da ABB nível a nível, da esquerda para a direita.
Exemplo para a árvore do Exercício 2:
Use uma fila (pode implementar com vetor circular ou lista encadeada).
Exercício 15 — Contagem de Nós por Faixa de Altura¶
Implemente:
Retorna quantos nós estão em níveis (profundidade) entre h_min e h_max (raiz = nível 0).
🔹 Bônus: Aplicações Práticas¶
Exercício B1 — Conjuntos com ABB¶
Implemente um TAD simples de conjunto usando ABB:
Arvore* conjunto_criar(void);
Arvore* conjunto_inserir(Arvore* c, int valor);
int conjunto_pertence(Arvore* c, int valor);
Arvore* conjunto_uniao(Arvore* a, Arvore* b); // Retorna nova ABB com união
Arvore* conjunto_interseccao(Arvore* a, Arvore* b); // Retorna nova ABB com interseção
Exercício B2 — Contagem de Ocorrências (Com Duplicatas Permitidas)¶
Modifique a estrutura para permitir contagem:
typedef struct Arvore {
int valor;
int ocorrencias; // novo campo
struct Arvore* esquerda;
struct Arvore* direita;
} Arvore;
Implemente:
Arvore* inserir_com_contagem(Arvore* raiz, int valor);
int contar_ocorrencias(Arvore* raiz, int valor);
Exercício B3 — Transformação: ABB → Lista Encadeada Ordenada¶
Implemente:
typedef struct NoLista {
int valor;
struct NoLista* prox;
} NoLista;
NoLista* abr_para_lista(Arvore* raiz);
Retorna uma lista encadeada com os valores da ABB em ordem crescente.
Dica: use
em_ordempara percorrer e construir a lista.
📦 Arquivo Cabeçalho Sugerido (abb.h)¶
#ifndef ABB_H
#define ABB_H
typedef struct Arvore {
int valor;
struct Arvore* esquerda;
struct Arvore* direita;
} Arvore;
// Funções fornecidas
Arvore* criar_arvore(int valor, Arvore* esq, Arvore* dir);
void liberar_arvore(Arvore* raiz);
void em_ordem(Arvore* raiz);
// Operações fundamentais
Arvore* inserir_abr(Arvore* raiz, int valor);
Arvore* buscar_abr(Arvore* raiz, int alvo);
int minimo_abr(Arvore* raiz);
int maximo_abr(Arvore* raiz);
int eh_abr(Arvore* raiz);
// Remoção e navegação
Arvore* remover_abr(Arvore* raiz, int valor);
Arvore* sucessor_abr(Arvore* raiz, int valor);
Arvore* antecessor_abr(Arvore* raiz, int valor);
// Consultas avançadas
int contar_no_intervalo(Arvore* raiz, int min, int max);
int altura_abr(Arvore* raiz);
Arvore* construir_abr_balanceada(int vet[], int inicio, int fim);
void imprimir_por_niveis(Arvore* raiz);
#endif
✅ Critérios de Avaliação Sugeridos¶
| Critério | Pontuação |
|---|---|
| Correção da propriedade ABB nas operações | 30% |
| Eficiência: aproveitamento da ordenação (evitar percursos desnecessários) | 25% |
| Tratamento de casos-base e borda (árvore vazia, nó único, remoção de raiz) | 20% |
| Clareza, recursão bem estruturada e comentários | 15% |
| Liberação correta de memória e ausência de vazamentos | 10% |
💡 Dicas Estratégicas para Resolução¶
- Desenhe antes de codificar: esboce a árvore e simule a operação manualmente.
- Pense nos casos-base primeiro:
raiz == NULLé seu amigo na recursão. - Validação de ABB exige limites: não compare apenas com o pai — use
min/maxpropagados. - Remoção com dois filhos: escolha sucessor ou antecessor, mas seja consistente.
- Teste incrementalmente:
- Árvore vazia → inserir 1 elemento → inserir em ordem crescente/decrescente → árvore balanceada.
Próximo passo sugerido
Após dominar esta lista, explore árvores AVL ou Rubro-Negras para entender balanceamento automático e garantia de altura logarítmica.
Material elaborado para a disciplina de Estrutura de Dados — Curso de Engenharia de Computação
Prof. Sérgio Souza Costa | Atualizado: 2026