O documento discute árvores binárias de busca, definindo suas propriedades e operações básicas como busca, inserção e remoção de elementos. Explica que as árvores binárias de busca mantêm uma ordem entre os elementos dos nós, tornando eficiente buscas, inserções e remoções.
2. São estruturas de dados adequadas para a
representação de hierarquias.
Uma árvore é composta por um conjunto de
nós.
Existe um nó r, denominado raiz, que contém
zero ou mais subárvores, cujas raízes são
ligadas diretamente a r.
A raiz se liga a um ou mais elementos, e cada
um destes forma uma nova subárvore. Esses
elementos são seus galhos ou filhos.
3. Fundamentos básicos
◦ GRAU – número de subárvores de um nó.
◦ FOLHA – um nó que possui grau zero, ou seja,
não possui subárvores.
◦ FILHOS – são as raízes das subárvores de um
nó.
◦ Nó não terminal é um nó que não é uma folha
e é diferente da raiz.
4. Fundamentos básicos
◦ A altura de uma árvore é o comprimento do
caminho mais longo da raiz até uma das
folhas.
◦ Uma árvore nula tem altura 0.
◦ Todos os nós são acessíveis a partir da raiz.
◦ Existe um único caminho entre a raiz e
qualquer outro nó.
6. Árvore Binária: Uma árvore binária é uma
árvore que pode ser nula, ou então tem as
seguintes características:
◦ Existe um nó especial denominado raiz;
◦ Nenhum nó tem grau superior a 2 (dois), isto
é, nenhum nó tem mais de dois filhos;
◦ Existe um “senso de posição”, ou seja,
distingue-se entre uma subárvore esquerda e
uma subárvore direita.
7. Atravessamento (ou caminhamento) de árvore
é a passagem de forma sistemática por cada
um de seus nós;
Diferentes formas de percorrer os nós de uma
árvore:
◦ Pré-ordem ou prefixa (busca em
profundidade)
◦ Em ordem ou infixa (ordem central)
◦ Pós-ordem ou posfixa
◦ Em nível
8. Pré-ordem (prefixa)
◦ visitar a raiz;
◦ caminhar na subárvore à esquerda, segundo
este caminhamento;
◦ caminhar na subárvore à direita, segundo este
caminhamento.
9. Atravessamento em ordem (infixa)
◦ caminhar na subárvore à esquerda, segundo
este caminhamento;
◦ visitar a raiz;
◦ caminhar na subárvore à direita, segundo este
caminhamento.
10. Atravessamento pós-ordem (posfixa)
◦ a) caminhar na subárvore à esquerda, segundo
este caminhamento;
◦ b) caminhar na subárvore à direita, segundo
este caminhamento;
◦ c) visitar a raiz.
11. Atravessamento em nível
◦ Percorre-se a árvore de cima para baixo e da
direita para a esquerda.
12. Árvore Estritamente Binária:
◦ É uma árvore binária na qual todo nó tem 0 ou
2 subárvores, ou seja, nenhum nó tem “filho
único”.
13. Árvore Binária Cheia
◦ Todos os nós, exceto os do último nível,
possuem exatamente duas subárvores.
◦ Uma árvore binária cheia de altura h tem 2h –
1 nós.
14. Árvore Degenerada
◦ Cada nó possui exatamente um filho, e a
árvore tem o mesmo número de níveis que de
nós
15. Uma árvore é denominada árvore binária de
busca se:
◦ Todo elemento da subárvore esquerda é
menor que o elemento raiz;
◦ Nenhum elemento da subárvore direita é
menor que o elemento raiz;
◦ As subárvores direita e esquerda também são
árvores de busca binária.
16. Busca
◦ Se o valor for igual à raiz, o valor existe na
árvore.
◦ Se o valor for menor do que a raiz, então deve
buscar-se na subárvore da esquerda, e assim
recursivamente, em todos os nós da
subárvore.
◦ Se o valor for maior que a raiz, deve-se buscar
na subárvore da direita, até alcançar-se o nó
folha da árvore, encontrando ou não o valor
requerido.
17. Inserção
◦ Se a árvore estiver vazia, cria um novo no e
insere as informações do novo nó.
◦ Compara a chave a ser inserida com a chave
do nó analisado:
Se menor, insere a chave na subárvore esquerda;
Se maior, insere a chave na subárvore direita.
19. Remoção
A remoção de um nó é um processo mais
complexo. Para excluir um nó de uma árvore
binária de busca, há de se considerar três
casos distintos:
◦ Remoção na folha
◦ Remoção de um nó com um filho
◦ Remoção de um nó com dois filhos
20. Remoção na folha
◦ A exclusão na folha é a mais simples, basta
removê-lo da árvore.
21. Remoção de um nó com um filho
◦ Excluindo-o, o filho sobe para a posição do
pai.
22. Remoção de um nó com dois filhos
◦ Neste caso, pode-se operar de duas maneiras
diferentes:
Substitui-se o valor do nó a ser retirado pelo
valor sucessor (o nó mais à esquerda da
subárvore direita);
Substitui-se o valor do nó a ser retirado pelo
valor antecessor (o nó mais à direita da
subárvore esquerda)
23. Remoção de um nó com dois filhos
◦ Exemplo de remoção substituindo o nó pelo
seu antecessor.
24. Remoção de um nó com dois filhos
◦ Exemplo de remoção substituindo o nó pelo
seu sucessor.
25. Árvore é representada pelo ponteiro para o nó raiz
public class NoArvore {
int info;
NoArvore direita;
NoArvore esquerda;
}
26. Imprime os valores da árvore em ordem crescente,
percorrendo os nós em ordem simétrica
void abb_imprime (NoArvore a)
{
if (a != null) {
abb_imprime(a.esquerda);
System.out.println(a.info+"n");
abb_imprime(a.direita);
}
}
27. Explora a propriedade de ordenação da árvore
Possui desempenho computacional proporcional à
altura
NoArvore abb_busca (NoArvore r, int v)
{
if (r == null)
return null;
else if (r.info > v)
return abb_busca (r.esquerda, v);
else if (r.info < v)
return abb_busca (r.direita, v);
else return r;
}
28. recebe um valor v a ser inserido
retorna o eventual novo nó raiz da (sub-)árvore
para adicionar v na posição correta, faça:
◦ se a (sub-)árvore for vazia
crie uma árvore cuja raiz contém v
◦ se a (sub-)árvore não for vazia
compare v com o valor na raiz
insira v na sae ou na sad, conforme o resultado da
comparação
29. NoArvore abb_insere (NoArvore a, int v)
{
if (a==null) {
a = new NoArvore();
a.info = v;
a.esquerda = a.direita = null;
}
else if (v < a.info)
a.esquerda = abb_insere(a.esquerda,v);
else /* v >= a->info */
a.direita = abb_insere(a.direita,v);
return a;
}
é necessário atualizar os ponteiros para
as sub-árvores à esquerda ou à direita
quando da chamada recursiva da função,
pois a função de inserção pode alterar
o valor do ponteiro para a raiz da (sub-)árvore.
31. recebe um valor v a ser inserido
retorna a eventual nova raiz da árvore
para remover v, faça:
◦ se a árvore for vazia
nada tem que ser feito
◦ se a árvore não for vazia
compare o valor armazenado no nó raiz com v
se for maior que v, retire o elemento da sub-árvore à
esquerda
se for menor do que v, retire o elemento da sub-
árvore à direita
se for igual a v, retire a raiz da árvore
32. para retirar a raiz da árvore, há 3 casos:
◦ caso 1: a raiz que é folha
◦ caso 2: a raiz a ser retirada possui um único filho
◦ caso 3: a raiz a ser retirada tem dois filhos
33. Caso 1: a raiz da sub-árvore é folha da árvore
original
◦ libere a memória alocada pela raiz
◦ retorne a raiz atualizada, que passa a ser NULL
34. Caso 2: a raiz a ser retirada possui um único filho
◦ libere a memória alocada pela raiz
◦ a raiz da árvore passa a ser o único filho da raiz
35. Caso 3: a raiz a ser retirada tem dois filhos
◦ encontre o nó N que precede a raiz na ordenação
◦ (o elemento mais à direita da sub-árvore à esquerda)
◦ troque o dado da raiz com o dado de N
◦ retire N da sub-árvore à esquerda
◦ (que agora contém o dado da raiz que se deseja retirar)
retirar o nó N mais à direita é trivial, pois N é um nó folha ou
N é um nó com um único filho (no caso, o filho da direita
nunca existe)
36. NoArvore abb_retira (NoArvore r, int v)
{
if (r == null)
return null;
else if (r.info > v)
r.esquerda = abb_retira(r.esquerda, v);
else if (r.info < v)
r.direita = abb_retira(r.direita, v);
else { /* achou o nó a remover */
/* nó sem filhos */
if (r.esquerda == null && r.direita == null) {
//free (r);
r = null;
}
/* nó só tem filho à direita */
else if (r.esquerda == null) {
NoArvore t = r;
r = r.direita;
//free (t);
}
37. /* só tem filho à esquerda */
else if (r.direita == null) {
NoArvore t = r;
r = r.esquerda;
//free (t);
}
/* nó tem os dois filhos */
else {
NoArvore f = r.esquerda;
while (f.direita != null) {
f = f.direita;
}
r.info = f.info; /* troca as informações */
f.info = v;
r.esquerda = abb_retira(r.esquerda,v);
}
}
return r;
}