Lista de exercícios
Aula prática 09: árvores binárias de busca
16 exercícios sobre representação, operações, percursos, medidas e balanceamento de ABB, com tarefas curtas e soluções comentadas.
Esta lista é para praticar o conteúdo, sem correção individual. Use Resposta esperada para comparação e autocorreção. Faça os desenhos no papel ou na ferramenta que preferir. Os trechos em C usam a representação e os nomes da implementação da aula. Não é necessário montar um programa completo. O tempo estimado inclui tentativa e conferência.
Convenções: cada exercício começa no estado apresentado, independentemente dos anteriores. Dentro de uma sequência, as operações são cumulativas. NULL significa ausência de nó ou de endereço válido, conforme o contexto. A raiz está no nível 1. A altura conta níveis: árvore vazia tem altura 0 e folha tem altura 1. Considere as alocações bem-sucedidas, salvo quando o exercício apresentar uma falha.
Representação em C: cada struct NO guarda info, esq e dir. O tipo ArvBin representa um ponteiro para nó. ArvBin* raiz aponta para uma alocação separada que guarda esse ponteiro, chamada aqui de caixa da raiz.
/* Um nó guarda a chave e os endereços dos filhos. */
struct NO{
int info;
struct NO *esq;
struct NO *dir;
};
/* ArvBin representa o endereço de um nó. */
typedef struct NO* ArvBin;
raiz é o endereço da caixa. *raiz é seu conteúdo, o endereço do primeiro nó. (*raiz)->info acessa a chave desse nó. -> acessa um campo pelo ponteiro e & obtém um endereço. Assim, &((*raiz)->esq) permite tratar o campo esquerdo como a caixa de uma subárvore. Só use *raiz se raiz != NULL e só acesse os campos se *raiz != NULL.
= atribui, == compara e return encerra a chamada atual. malloc reserva memória e pode retornar NULL. free libera uma alocação sem atualizar automaticamente quem guardava seu endereço. Os trechos de funções pressupõem as declarações da implementação e as bibliotecas <stdlib.h> e <stdio.h>. As funções auxiliares libera_NO e remove_atual são usadas dentro de ArvoreBinaria.c.
Exercício 1: verificar a propriedade da ABB
Observe a posição de cada nó. Para verificar uma ABB, considere todos os descendentes de cada subárvore.
Classifique a estrutura e justifique:
- É uma árvore binária?
- É uma árvore binária de busca?
Solução
Explicação
Uma árvore binária admite no máximo dois filhos por nó e distingue esquerda de direita. Isso não determina a ordem dos valores. Embora 50 seja maior que seu pai 20, ele está na subárvore esquerda de 40. A propriedade da ABB também precisa valer em relação a esse ancestral.
Objetivo de aprendizagem: verificar a ordenação de uma subárvore inteira, distinguindo uma árvore binária de uma ABB.
Resposta esperada
É uma árvore binária: nenhum nó possui mais de dois filhos, e suas posições estão identificadas. Não é uma ABB: 50 pertence à subárvore esquerda de 40, mas . Comparar somente cada filho com seu pai não detectaria essa violação.
Exercício 2: criar a árvore sem criar um nó
Observe os estados A, B e C. A e B mostram o resultado da criação. Em C, um nó já foi inserido.
Responda com base na imagem:
- Associe A, B e C a: falha de criação, árvore vazia e árvore com um nó.
- Em C, quais são os valores de
info,esqedir? - Por que a caixa da raiz não conta como nó?
Solução
Explicação
cria_ArvBin reserva a caixa da raiz. Ela ainda não cria um struct NO. malloc faz essa reserva, e sizeof(ArvBin) informa o espaço necessário.
ArvBin* cria_ArvBin(){
ArvBin* raiz = (ArvBin*) malloc(sizeof(ArvBin));
if(raiz != NULL)
*raiz = NULL;
return raiz;
}
Se a reserva falha, raiz recebe NULL. Se funciona, a caixa existe e guarda NULL até a inserção do primeiro nó.
Objetivo de aprendizagem: distinguir a referência de controle, a árvore vazia e o primeiro nó para interpretar corretamente a criação da ABB.
Resposta esperada
- A: falha de criação. B: árvore criada e vazia. C: árvore com um nó.
- Em C:
(*raiz)->info = 26,(*raiz)->esq = NULLe(*raiz)->dir = NULL. - A caixa guarda o endereço do primeiro nó. Ela não tem os campos de um
struct NOe não ocupa uma posição na árvore.
Exercício 3: inserir chaves e descartar uma duplicata
Faça um rastreamento manual das inserções. Use o código abaixo como referência para acompanhar os passos no desenho.
novo é o nó candidato. atual percorre a árvore, e ant guarda o pai.
As verificações iniciais tratam falhas de alocação. O laço procura uma posição vazia e descarta duplicatas. A comparação final liga o novo nó ao pai.
A função retorna 1 ao inserir e 0 para duplicata, falha de alocação ou caixa inexistente.
int insere_ArvBin(ArvBin* raiz, int valor){
if(raiz == NULL)
return 0;
struct NO* novo;
novo = (struct NO*) malloc(sizeof(struct NO));
if(novo == NULL)
return 0;
novo->info = valor;
novo->dir = NULL;
novo->esq = NULL;
if(*raiz == NULL)
*raiz = novo;
else{
struct NO* atual = *raiz;
struct NO* ant = NULL;
while(atual != NULL){
ant = atual;
if(valor == atual->info){
free(novo);
return 0;//elemento já existe
}
if(valor > atual->info)
atual = atual->dir;
else
atual = atual->esq;
}
if(valor > ant->info)
ant->dir = novo;
else
ant->esq = novo;
}
return 1;
}
Considere que ArvBin* raiz = cria_ArvBin(); já criou uma árvore vazia. Faça um trace manual do código simulando as inserções de 32, 18, 46, 25, 38 e 18, nessa ordem, com insere_ArvBin(raiz, valor).
Desenhe os estados intermediários que precisar para acompanhar as inserções. Na última tentativa, anote o retorno da função.
Na resposta esperada, você encontrará apenas a árvore final e o retorno da última tentativa para conferir seu raciocínio.
Solução
Explicação
Cada chave segue as comparações desde a raiz até uma posição vazia. Para 25, o caminho passa por 32 e 18. Para 38, passa por 32 e 46. Na última tentativa, o laço encontra valor == atual->info no nó 18. O nó candidato é liberado e a árvore permanece igual.
Objetivo de aprendizagem: executar inserções preservando a ordem da ABB e reconhecer que uma duplicata não cria outro nó.
Resposta esperada
A última tentativa de inserir 18 retorna 0, pois a chave já existe. A árvore permanece com 5 nós.
Exercício 4: rastrear uma busca com e sem sucesso
Observe os filhos de cada nó. Os campos NULL mostram onde uma busca pode terminar sem encontrar a chave.
Rastreie as buscas por 55 e por 25, cada uma começando na raiz. Use busca_ArvBin(raiz, valor).
Para cada busca, registre:
- Os nós examinados, na ordem.
- A direção de cada descida (
esqoudir). - O retorno da função. Inclua o
NULLfinal no caminho se a chave estiver ausente.
Apoio em C:
Leia o código de busca da aula. atual começa no primeiro nó. O laço compara a chave e segue apenas uma subárvore.
A busca retorna o endereço do nó encontrado ou NULL. O return 0 inicial também representa um ponteiro nulo.
struct NO* busca_ArvBin(ArvBin *raiz, int valor){
if(raiz == NULL)
return 0;
struct NO* atual = *raiz;
while(atual != NULL){
if(valor == atual->info){
return atual;
}
if(valor > atual->info)
atual = atual->dir;
else
atual = atual->esq;
}
return NULL;
}
Solução
Explicação
55 é maior que 45 e menor que 70. A igualdade com o próximo nó encerra essa busca. Já 25 é menor que 45, maior que 20 e menor que 30. O último passo procura o filho esquerdo de 30, que não existe. Não é necessário examinar o outro lado da árvore.
Objetivo de aprendizagem: selecionar a subárvore possível em cada comparação e distinguir encontro de chave de término em posição vazia.
Resposta esperada
- Busca por 55: 45 → direita → 70 → esquerda → 55. Retorna a referência ao nó de chave 55.
- Busca por 25: 45 → esquerda → 20 → direita → 30 → esquerda →
NULL. RetornaNULL.
Exercício 5: rastrear a exibição em Pré-Ordem
Observe as ligações da árvore. O percurso pode começar em qualquer nó e visitar a subárvore que começa nele.
Qual sequência será exibida por preOrdem_NO(no), com no apontando para o nó 7? Escreva os valores na ordem de exibição.
Apoio em C:
Use a mesma struct NO da aula. A função recebe diretamente um ponteiro para nó. Ela exibe info, percorre esq e depois dir.
/* Exibe em Pré-Ordem a subárvore que começa em no. */
void preOrdem_NO(struct NO* no){
/* Encerra o ramo vazio para evitar acesso a um nó inexistente. */
if(no == NULL)
return;
printf("%d\n", no->info);
preOrdem_NO(no->esq);
preOrdem_NO(no->dir);
}
Solução
Explicação
O percurso exibe 7 e conclui sua subárvore esquerda, iniciada em 3, antes de começar a direita, iniciada em 12.
Em 3, visita primeiro 1 e depois a subárvore de 5. O nó 5 é exibido antes de seus filhos 4 e 6. Na subárvore direita de 7, visita 12, depois 9 e 15. Os nós 18 e 29 ficam fora do percurso.
Objetivo de aprendizagem: rastrear a visita antes das subárvores para determinar a sequência em Pré-Ordem.
Resposta esperada
7, 3, 1, 5, 4, 6, 12, 9, 15.
Exercício 6: rastrear a exibição em Em-Ordem
Observe a mesma árvore do exercício 5. O ponteiro no indica o início do percurso.
Faça um trace manual de exibir_em_ordem(no), com no apontando para o nó 7, e escreva a sequência exibida.
Apoio em C:
void exibir_em_ordem(struct NO* no) {
if (no == NULL) {
return;
}
exibir_em_ordem(no->esq);
printf("%d\n", no->info);
exibir_em_ordem(no->dir);
}
Solução
Explicação
Em-Ordem conclui a subárvore esquerda, exibe o nó e percorre a direita. Como o percurso começa em 7, os nós 18 e 29 ficam de fora. Os valores da subárvore de 7 aparecem em ordem crescente porque ela é uma ABB.
Objetivo de aprendizagem: rastrear a visita entre as subárvores para determinar a sequência em Em-Ordem.
Resposta esperada
O trace pode ser agrupado pelas partes da subárvore de 7:
| Parte visitada | Valores exibidos |
|---|---|
| Subárvore esquerda de 7 | 1, 3, 4, 5, 6 |
| Nó 7 | 7 |
| Subárvore direita de 7 | 9, 12, 15 |
Sequência completa: 1, 3, 4, 5, 6, 7, 9, 12, 15.
Exercício 7: rastrear a exibição em Pós-Ordem
Observe a mesma árvore do exercício 5. O ponteiro no indica o início do percurso.
Faça um trace manual de exibir_pos_ordem(no), com no apontando para o nó 7, e escreva a sequência exibida.
Apoio em C:
void exibir_pos_ordem(struct NO* no) {
if (no == NULL) {
return;
}
exibir_pos_ordem(no->esq);
exibir_pos_ordem(no->dir);
printf("%d\n", no->info);
}
Solução
Explicação
Pós-Ordem conclui as subárvores esquerda e direita antes de exibir o nó. Assim, 3 aparece depois de seus descendentes, 12 aparece depois de 9 e 15, e 7 é o último valor exibido. Os nós 18 e 29 ficam fora do percurso.
Objetivo de aprendizagem: rastrear a visita depois das subárvores para determinar a sequência em Pós-Ordem.
Resposta esperada
O trace pode ser agrupado pelas partes da subárvore de 7:
| Parte visitada | Valores exibidos |
|---|---|
| Subárvore esquerda de 7 | 1, 4, 6, 5, 3 |
| Subárvore direita de 7 | 9, 15, 12 |
| Nó 7 | 7 |
Sequência completa: 1, 4, 6, 5, 3, 9, 15, 12, 7.
Exercício 8: liberar a memória de todos os nós da árvore
Considere o fim do uso da árvore: todos os nós serão liberados da memória.
Onde colocar free(no); para destruir todos os nós?
- Indique A, B ou C para liberar todos os nós com segurança. Deixe as outras posições vazias.
- Escreva a ordem dos valores de
infodos registros liberados.
Apoio em C:
A função libera_NO é a auxiliar recursiva de libera_ArvBin no código da aula. Os comentários A, B e C marcam as posições possíveis para acrescentar free(no);.
free(no) libera apenas o registro indicado. Seus campos não podem ser acessados depois da liberação. A função percorre esq antes de dir.
/* Libera os nós; a posição da liberação deve preservar os filhos. */
void libera_NO(struct NO* no){
/* Uma posição vazia não possui registro para liberar. */
if(no == NULL)
return;
/* A */
libera_NO(no->esq);
/* B */
libera_NO(no->dir);
/* C */
}
Solução
Explicação
O registro do pai precisa existir enquanto suas referências aos filhos são usadas. A liberação deve acontecer depois das duas chamadas, em Pós-Ordem. Assim, a chamada de 7 termina antes da chamada de 29, e a raiz é liberada por último.
Essa é uma destruição completa. As ligações não precisam ser reorganizadas, pois nenhum nó será mantido para uso posterior.
Objetivo de aprendizagem: escolher o momento da liberação para preservar o acesso aos filhos durante a destruição recursiva.
Resposta esperada
Posição C, imediatamente depois de libera_NO(no->dir);. A ordem de liberação é 11, 7, 29, 18.
Exercício 9: encerrar a destruição da caixa da raiz
Considere que raiz aponta para uma caixa válida. libera_NO(*raiz) já libera todos os nós, mas a caixa é uma alocação separada.
/* Libera os nós e, em seguida, a caixa da raiz. */
void libera_ArvBin(ArvBin* raiz){
/* Sem caixa, não há memória a devolver. */
if(raiz == NULL)
return;
libera_NO(*raiz);
/* Acrescente aqui a liberação da caixa. */
}
No chamador, a variável ArvBin* raiz já existe:
libera_ArvBin(raiz);
/* Acrescente aqui a atualização da variável do chamador. */
Complete os dois pontos indicados com instruções em C:
- Na função, libere a caixa da raiz.
- No chamador, faça
raizdeixar de guardar o endereço liberado.
Solução
Explicação
raiz e *raiz se referem a alocações diferentes:
raiz: endereço da caixa alocada porcria_ArvBin.*raiz: conteúdo da caixa, que guarda o endereço do primeiro nó ouNULLquando a árvore está vazia.
libera_NO(*raiz) já libera todos os nós, inclusive o primeiro. Depois disso, usamos free(raiz) para liberar a caixa. Usar free(*raiz) não liberaria a caixa e, se a árvore tinha nós, tentaria liberar o primeiro nó novamente.
A função recebe uma cópia do endereço da caixa. Por isso, o próprio chamador precisa atualizar sua variável após o retorno. Ele não deve liberar a caixa novamente.
Objetivo de aprendizagem: concluir a liberação da representação, distinguindo a memória dos nós da memória da caixa da raiz.
Resposta esperada
Na função, acrescente free(raiz);. O resultado coincide com o código da aula:
void libera_ArvBin(ArvBin* raiz){
if(raiz == NULL)
return;
libera_NO(*raiz);//libera cada nó
free(raiz);//libera a raiz
}
No chamador:
libera_ArvBin(raiz);
raiz = NULL;
Exercício 10: distinguir contagem e altura
Compare duas funções que recebem um ponteiro para o nó inicial de uma subárvore:
/* Retorna a quantidade de nós da subárvore que começa em no. */
int contar_nos(struct NO* no);
/* Retorna a altura em níveis da subárvore que começa em no. */
int calcular_altura(struct NO* no);
no pode apontar para qualquer nó. Quando no == NULL, as duas funções já retornam 0.
Dentro de contar_nos, as contagens das subárvores já foram calculadas:
int total_esquerda = contar_nos(no->esq);
int total_direita = contar_nos(no->dir);
Dentro de calcular_altura, as alturas das subárvores também já foram calculadas:
int altura_esquerda = calcular_altura(no->esq);
int altura_direita = calcular_altura(no->dir);
Complete o final de cada função, em C:
- Escreva o
returndecontar_nos. - Escreva o final de
calcular_altura. Useifpara escolher o caminho mais longo.
Não é necessário escrever as funções inteiras.
Solução
Explicação
A contagem reúne todos os nós das duas subárvores e inclui o nó atual. A altura acompanha somente o caminho mais longo e acrescenta o nível do nó atual. As funções combinam os retornos recursivos de maneiras diferentes.
Um ponteiro para nó basta para acessar seus filhos e consultar a subárvore. Essas funções não alteram qual nó o ponteiro do chamador indica, por isso recebem struct NO* no.
Objetivo de aprendizagem: distinguir a soma de quantidades da escolha do maior caminho ao combinar resultados recursivos de subárvores.
Resposta esperada
Final de contar_nos:
return 1 + total_esquerda + total_direita;
Final de calcular_altura, como na implementação:
/* Apenas o maior caminho determina a altura. */
if (altura_esquerda > altura_direita) {
return 1 + altura_esquerda;
}
return 1 + altura_direita;
Em ambas, uma folha retorna 1, pois suas duas subárvores vazias retornam 0.
Exercício 11: rastrear a remoção de uma folha
Considere que raiz aponta para a caixa da árvore abaixo.
Faça um trace manual da chamada remove_ArvBin(raiz, 36) usando as duas funções abaixo.
Apoio em C:
int remove_ArvBin(ArvBin *raiz, int valor){
if(raiz == NULL)
return 0;
struct NO* ant = NULL;
struct NO* atual = *raiz;
while(atual != NULL){
if(valor == atual->info){
if(atual == *raiz)
*raiz = remove_atual(atual);
else{
if(ant->dir == atual)
ant->dir = remove_atual(atual);
else
ant->esq = remove_atual(atual);
}
return 1;
}
ant = atual;
if(valor > atual->info)
atual = atual->dir;
else
atual = atual->esq;
}
return 0;
}
struct NO* remove_atual(struct NO* atual){
struct NO *no1, *no2;
if(atual->esq == NULL){
no2 = atual->dir;
free(atual);
return no2;
}
no1 = atual;
no2 = atual->esq;
while(no2->dir != NULL){
no1 = no2;
no2 = no2->dir;
}
if(no1 != atual){
no1->dir = no2->esq;
no2->esq = atual->esq;
}
no2->dir = atual->dir;
free(atual);
return no2;
}
Solução
Explicação
remove_ArvBin localiza 36 e usa o retorno de remove_atual para atualizar a ligação no pai. Como 36 é uma folha, a auxiliar retorna NULL.
Objetivo de aprendizagem: remover uma folha substituindo sua referência por NULL, sem alterar os demais nós.
Resposta esperada
Um trace possível é o da tabela. Os números identificam o campo info dos nós apontados.
| Momento | Estado ou ação |
|---|---|
| Início | ant é NULL e atual aponta para 52. |
| Primeira descida | ant aponta para 52 e atual para 24. |
| Segunda descida | ant aponta para 24 e atual para 36. |
| Chave encontrada | Chama remove_atual(atual). |
Primeiro if | Como atual não tem filho esquerdo, entra no primeiro if. |
| Liberação do nó | Na auxiliar, no2 recebe NULL, o nó 36 é liberado e a chamada retorna NULL. |
| Retorno ao chamador | ant->dir recebe NULL e remove_ArvBin retorna 1. |
Confira a árvore após a remoção:
Exercício 12: rastrear a remoção da raiz com um filho
Considere que raiz aponta para a caixa da árvore abaixo.
Faça um trace manual da chamada remove_ArvBin(raiz, 52) usando as funções remove_ArvBin e remove_atual do exercício 11.
Solução
Explicação
A auxiliar retorna o endereço de 76, que passa a ser guardado em *raiz. Somente o nó 52 é liberado. O nó 76 mantém sua ligação com 60, e a caixa da raiz permanece alocada.
Objetivo de aprendizagem: promover uma subárvore inteira ao remover uma raiz com um filho, preservando seus descendentes.
Resposta esperada
Um trace possível é o da tabela. Os números identificam o campo info dos nós apontados.
| Momento | Estado ou ação |
|---|---|
| Início | ant é NULL e atual aponta para 52. |
| Chave encontrada | valor == atual->info e atual == *raiz. Chama remove_atual(atual) para atualizar a caixa da raiz. |
Primeiro if da auxiliar | Como atual não tem filho esquerdo, entra no primeiro if. |
| Liberação do nó | no2 recebe o endereço de 76, o nó 52 é liberado e a auxiliar retorna no2. |
| Retorno ao chamador | *raiz recebe o endereço de 76 e remove_ArvBin retorna 1. |
Confira a árvore após a remoção. A seta mais espessa destaca a atualização de *raiz:
Exercício 13: localizar os substitutos de um nó com dois filhos
Observe as duas subárvores da raiz 60. Para achar o maior valor de uma subárvore, siga dir. Para achar o menor, siga esq.
Localize os dois candidatos a substituir 60:
- O maior nó da subárvore esquerda.
- O menor nó da subárvore direita.
Para cada candidato, escreva o caminho a partir da raiz da subárvore e o valor de info. A função remove_atual da aula usa o maior da esquerda.
Solução
Explicação
A procura do maior começa na raiz da subárvore esquerda e termina quando não há filho direito. A procura do menor começa na raiz da subárvore direita e termina quando não há filho esquerdo. São os vizinhos de 60 na ordem crescente.
Objetivo de aprendizagem: localizar os extremos que preservam a ordenação ao substituir um nó com dois filhos.
Resposta esperada
- Maior da esquerda: caminho 30 → 45, candidato 45.
- Menor da direita: caminho 90 → 75, candidato 75.
Exercício 14: rastrear a remoção da raiz com dois filhos
Considere que raiz aponta para a caixa da árvore abaixo.
Faça um trace manual da chamada remove_ArvBin(raiz, 64) usando as funções remove_ArvBin e remove_atual do exercício 11.
Perceba que nesse caso, vai acontecer uma busca pelo nó de maior valor da subárvore esquerda.
Solução
Explicação
48 substitui 64 na raiz. Antes disso, o campo dir de 32 recebe o endereço de 40, preservando esse descendente. O nó 48 recebe as subárvores de raízes 32 e 88. Somente o nó 64 é liberado.
Objetivo de aprendizagem: atualizar as referências da remoção com dois filhos sem perder a subárvore do nó promovido.
Resposta esperada
Um trace possível é o da tabela. Os números identificam o campo info dos nós apontados.
| Momento | Estado ou ação |
|---|---|
| Início | ant é NULL e atual aponta para 64. |
| Chave encontrada | valor == atual->info e atual == *raiz. Chama remove_atual(atual) para atualizar a caixa da raiz. |
Primeiro if da auxiliar | Como atual tem filho esquerdo, não entra no primeiro if. Em seguida, no1 aponta para 64 e no2 para 32. |
| Laço da auxiliar | no2->dir aponta para 48. Após uma repetição, no1 aponta para 32 e no2 para 48. O laço termina, pois no2->dir == NULL. |
Segundo if da auxiliar | no1 != atual, então entra no if. no1->dir = no2->esq; faz o campo dir de 32 receber o endereço de 40. |
| Ligação à esquerda | no2->esq = atual->esq; faz o campo esq de 48 receber o endereço de 32. |
| Ligação à direita | no2->dir = atual->dir; faz o campo dir de 48 receber o endereço de 88. |
| Liberação do nó | free(atual); libera o nó 64. A auxiliar retorna no2, que aponta para 48. |
| Retorno ao chamador | *raiz recebe o endereço de 48 e remove_ArvBin retorna 1. |
Confira a árvore após a remoção. As setas mais espessas destacam as referências alteradas:
Exercício 15: verificar o critério de balanceamento
Compare as árvores A e B, que contêm as mesmas chaves.
Considere balanceada uma árvore em que, em cada nó, as alturas das subárvores esquerda e direita diferem no máximo em 1.
Classifique A e B como balanceada ou não balanceada e justifique.
Solução
Explicação
O critério precisa valer em todos os nós. Em A, nenhum nó viola o limite. Em B, a diferença de alturas na raiz já permite rejeitar o balanceamento.
Objetivo de aprendizagem: aplicar o critério de balanceamento em toda a árvore e reconhecer uma violação local suficiente para rejeitá-lo.
Resposta esperada
A é balanceada. B não é balanceada. As alturas justificam as classificações:
| Árvore | Nós verificados | Altura de esq | Altura de dir | Diferença |
|---|---|---|---|---|
| A | 20 | 2 | 2 | 0 |
| A | 12 e 28 | 1 | 1 | 0 |
| A | Folhas 8, 16, 24 e 32 | 0 | 0 | 0 |
| B | 8 | 0 | 6 | 6 |
Em A, todos os nós atendem ao limite. Em B, a diferença 6 na raiz 8 ultrapassa 1.
Exercício 16: comparar os maiores caminhos de busca
Observe as árvores A e B. Cada seta entre dois nós representa uma aresta.
Compare a busca bem-sucedida mais longa em A e B, começando na raiz.
Para cada árvore, informe: altura em níveis, nós examinados e arestas percorridas.
Solução
Explicação
O maior caminho de uma busca bem-sucedida chega a uma folha no nível mais profundo. A visita inicial à raiz conta como um nó examinado. As arestas contam somente as descidas entre nós, por isso há uma aresta a menos que nós no caminho.
Objetivo de aprendizagem: relacionar altura ao limite da busca, distinguindo nós examinados de arestas percorridas.
Resposta esperada
A tabela compara o caminho mais longo de busca bem-sucedida em cada árvore.
| Árvore | Altura | Nós examinados, no máximo | Arestas percorridas, no máximo |
|---|---|---|---|
| A | 3 | 3 | 2 |
| B | 7 | 7 | 6 |
Exemplos que alcançam esses limites: 20 → 12 → 8 em A e 8 → 12 → 16 → 20 → 24 → 28 → 32 em B.