Estrutura de
Dados
Implementação da Arvore Binária
profa. Divani Barbosa
Aula 13 parte 2
2
É uma estrutura de dados caracterizada por:
 Ou não tem elemento algum (árvore vazia).
 Ou tem um elemento distinto, denominado raiz, com dois
apontamentos para dois elos diferentes, denominadas sub-
árvore esquerda e sub-árvore direita.
Arvore Binária
Exemplos:
a) b)
3
4
Arvores Balanceadas
 Uma arvore é considerada balanceada quando suas sub-
arvores a esquerda e a direita possuem a mesma altura.
 A arvore não balanceada é definida como degenerada.
Exemplos:
arvore binária
balanceada
arvore binária
degenerada
a) b)
5
Classe No
Uma arvore binária precisa de uma classe de
objetos Nós, assim como vimos na lista
duplamente encadeada:
class No {
public long item;
public No esq;
public No dir;
}
espaço para armazenamento da
informação (chave)
Um espaço para armazenar uma
referência da localização na
memória onde o Nó a esquerda
se encontra.
Um espaço para armazenar a
referência do Nó a direita.
6
Nó
esq =
dir =
item = 14
Nó
esq =
dir =
item = 4
Nó
esq =
dir =
item = 16
Nó
esq = NULL
dir = NULL
item = 3
Nó
esq = NULL
dir = NULL
item = 9
Nó
esq = NULL
dir = NULL
item = 15
Nó
esq = NULL
dir = NULL
item = 18
As referencias
são para outras
sub-arvores
root
Elos de uma arvore binária
7
Nó
esq =
dir =
item = 14
Nó
esq =
dir =
item = 4
Nó
esq =
dir =
item = 16
Nó
esq = NULL
dir = NULL
item = 3
Nó
esq = NULL
dir = NULL
item = 9
Nó
esq = NULL
dir = NULL
item = 15
Nó
esq = NULL
dir = NULL
item = 18
root = null
A árvore pode não ter nenhum elemento (árvore vazia)
Elos de uma arvore binária
8
Implementação
private No root;
Classe Tree:
Campo Construtor
public Tree() { root=null; }
Métodos
inserir: Insere itens na arvore
buscar: Retorna Nó procurado ou null
remover: Retorna verdadeiro se removeu item
no_sucessor: Retorna o Nó sucessor ao passado no
parâmetro
caminhar: (inOrder, preOrder, posOrder, altura,
folhas, min, max, contarNos)
Método: inserir
A inserção começa com a chave sendo atribuida a raiz,
logo após a função começa com uma busca, a-partir da
raiz, comparando a chave com o valor da raiz. Se a
chave é menor ou igual do que a raiz, ela é
introduzida num novo nó a esquerda da raiz, ou na
direita caso a chave seja maior que a raiz, e assim
sucessivamente, item a item, os nós são criados.
Exemplo:
Itens a serem adicionados:
25, 11, 42, 6, 19, 37 e 14
Método: inserir
public void inserir(long v) {
No novo = new No();
novo.item = v;
novo.dir = null;
novo.esq = null;
if (root == null)
root = novo;
else {
// inserir aqui
// trecho de código
// para tratamento
// caso árvore não vazia
}
}
Entrada: item que deseja inserir Saída: não há
Criando objeto Nó e
armazenando na referencia
novo
se arvore vazia
No atual = root;
No anterior;
while (true) {
anterior = atual;
if (v <= atual.item) {
atual = atual.esq;
if (atual == null) {
anterior.esq = novo;
return; }
}
else {
atual = atual.dir;
if (atual == null) {
anterior.dir = novo;
return; }
}
} // fim do laço while
trecho de código para tratamento caso não raiz (arvore não vazia)
começa a procurar desde raiz
Adiciona a esquerda
e sai
Adiciona a direita
e sai
Caminha para esquerda
Caminha para direita
Guarda o Nó anterior
12
Método: buscar
public No buscar(long chave) {
if (root == null) return null;
No atual = root;
while (atual.item != chave) {
if (chave < atual.item )
atual = atual.esq;
else
atual = atual.dir;
if (atual == null)
return null;
}
return atual;
}
Entrada: chave
Saída: Nó que procura ou null caso não encontre a chave
começa a procurar desde raiz
se arvore vazia
enquanto nao encontrou
caminha para esquerda
caminha para direita
encontrou uma folha -> sai
Saiu do laço while e chegou
aqui é porque encontrou item
Método: remover
O processo de exclusão de um nó é o mais complexo.
Para excluir um nó de uma árvore binária, deve-se
considerar três casos distintos:
Remoção da folha
A exclusão de um nó que se encontra no fim da árvore, isto é, na
folha, é o caso mais simples de exclusão. Basta remover o nó da
árvore
14
Remoção de um nó com “filho”
Caso o nó que será excluído tenha um único "filho", o "avô"
herda o "filho".
15
Remoção de um nó com dois “filhos”
Se o nó a ser excluído tiver dois "filhos", o processo de
exclusão poderá operar de duas maneiras diferentes:
Substituir o valor do nó a ser retirado pelo valor sucessor (o
nó mais à esquerda da sub-árvore direita).
Método: remover
public boolean remover(long v) {
if (root == null) return false;
No atual = root;
No pai = root;
boolean filho_esq = true;
while ( atual.item != v) {
pai = atual;
if ( v < atual.item ) {
atual = atual.esq;
filho_esq = true;
} else {
atual = atual.dir;
filho_esq = false;
}
if (atual == null) return false;
} // fim laço while busca
Entrada: item que deseja remover
Saída: verdadeiro ou falso
Enquanto não encontrou
Caminha a esquerda
Caminha a direita
Chegou em uma folha
public boolean remover(long v) {
if (root == null) return false;
No atual = root;
No pai = root;
boolean filho_esq = true;
while ( atual.item != v) {
pai = atual;
if ( v < atual.item ) {
atual = atual.esq;
filho_esq = true;
} else {
atual = atual.dir;
filho_esq = false;
}
if (atual == null) return false;
} // fim laço while busca
Método: remover
Entrada: item que deseja remover
Saída: verdadeiro ou falso
Se terminou o laço de busca
sem sair do método remover
quer dizer que:
 Encontrou o valor (v)
 "atual": contem a
referencia ao No a ser
eliminado
 "pai": contem a
referencia para o pai do
No a ser eliminado
 "filho_esq": é
verdadeiro se atual é filho
a esquerda do pai
Método: remover
Entrada: item que deseja remover
Saída: verdadeiro ou falso
atual.item =
pai.item =
filho_esq =
atual.item = 11
pai.item = 25
filho_esq = true
public boolean remover(long v) {
if (root == null) return false;
No atual = root;
No pai = root;
boolean filho_esq = true;
while ( atual.item != v) {
pai = atual;
if ( v < atual.item ) {
atual = atual.esq;
filho_esq = true;
} else {
atual = atual.dir;
filho_esq = false;
}
if (atual == null) return false;
} // fim laço while busca
if (atual.esq == null && atual.dir == null)
{
if (atual == root ) root = null;
else if (filho_esq) pai.esq = null;
else pai.dir = null;
}
Eliminando uma folha
atual.item = 6
pai.item = 11
filho_esq = true
Se não possui nenhum filho (é uma folha), elimine-o
Se é pai e não possui filho a direita
atual.item = 19
pai.item = 11
filho_esq = false
Substitui pela sub-árvore a direita
else if (atual.dir == null) {
if (atual == root) root = atual.esq;
else if (filho_esq) pai.esq = atual.esq;
else pai.dir = atual.esq;
}
pai.dir
atual.esq
Se é pai e não possui filho a esquerda
atual.item = 6
pai.item = 11
filho_esq = true
Substitui pela sub-árvore a esquerda
else if (atual.esq == null) {
if (atual == root) root = atual.dir;
else if (filho_esq) pai.esq = atual.dir;
else pai.dir = atual.dir;
}
pai.esq
atual.dir
Se possui mais de um filho
Se for um avô ou outro grau maior de parentesco
else {
No sucessor = no_sucessor(atual);
if (atual == root) root = sucessor;
else if (filho_esq) pai.esq = sucessor;
else pai.dir = sucessor;
sucessor.esq = atual.esq;
}
return true; // removeu item retorna true
} // fim método remover
Usando sucessor que seria a referencia ao Nó mais a esquerda da sub-
árvore a direita do Nó que deseja-se remover
No sucessor = no_sucessor(atual);
if (atual == root) root = sucessor;
else if (filho_esq) pai.esq = sucessor;
else pai.dir = sucessor;
sucessor.esq = atual.esq;
Trecho de código
atual.item = 11
pai.item = 25
filho_esq = true
1
2
3
4
5
public No no_sucessor(No apaga) {
No paidosucessor = apaga;
No sucessor = apaga;
No atual = apaga.dir;
while (atual != null) {
paidosucessor = sucessor;
sucessor = atual;
atual = atual.esq;
}
if (sucessor != apaga.dir) {
paidosucessor.esq = sucessor.dir;
sucessor.dir = apaga.dir;
}
return sucessor;
}
Método: no_sucessor
Retorno:
apaga
paisucessor
sucessor
atual
Entrada:
public No no_sucessor(No apaga) {
No paidosucessor = apaga;
No sucessor = apaga;
No atual = apaga.dir;
while (atual != null) {
paidosucessor = sucessor;
sucessor = atual;
atual = atual.esq;
}
if (sucessor != apaga.dir) {
paidosucessor.esq = sucessor.dir;
sucessor.dir = apaga.dir;
}
return sucessor;
}
Método: no_sucessor
Retorno:
apaga
sucessor
atual
paisucessor
sucessor
atual
Entrada:
paisucessor
public No no_sucessor(No apaga) {
No paidosucessor = apaga;
No sucessor = apaga;
No atual = apaga.dir;
while (atual != null) {
paidosucessor = sucessor;
sucessor = atual;
atual = atual.esq;
}
if (sucessor != apaga.dir) {
paidosucessor.esq = sucessor.dir;
sucessor.dir = apaga.dir;
}
return sucessor;
}
Método: no_sucessor
Retorno:
apaga
sucessor
atual
paisucessor
sucessor
atual
Entrada:
paisucessor
sucessor
atual = null
true
public No no_sucessor(No apaga) {
No paidosucessor = apaga;
No sucessor = apaga;
No atual = apaga.dir;
while (atual != null) {
paidosucessor = sucessor;
sucessor = atual;
atual = atual.esq;
}
if (sucessor != apaga.dir) {
paidosucessor.esq = sucessor.dir;
sucessor.dir = apaga.dir;
}
return sucessor;
}
Método: no_sucessor
Retorno:
apaga
sucessor
atual
paisucessor
sucessor
atual
sucessor
atual = null
Entrada:
true
paisucessor
sucessor
public No no_sucessor(No apaga) {
No paidosucessor = apaga;
No sucessor = apaga;
No atual = apaga.dir;
while (atual != null) {
paidosucessor = sucessor;
sucessor = atual;
atual = atual.esq;
}
if (sucessor != apaga.dir) {
paidosucessor.esq = sucessor.dir;
sucessor.dir = apaga.dir;
}
return sucessor;
}
Método: no_sucessor
Retorno:
apaga
sucessor
atual
paisucessor
sucessor
atual = null
Entrada:
true
paisucessor
sucessor
null
public No no_sucessor(No apaga) {
No paidosucessor = apaga;
No sucessor = apaga;
No atual = apaga.dir;
while (atual != null) {
paidosucessor = sucessor;
sucessor = atual;
atual = atual.esq;
}
if (sucessor != apaga.dir) {
paidosucessor.esq = sucessor.dir;
sucessor.dir = apaga.dir;
}
return sucessor;
}
Método: no_sucessor
sucessor
apaga
paisucessor
sucessor
atual
paisucessor
sucessor
atual = null
Entrada:
true
null
apaga.dir
Retorno:
atual.item = 11
pai.item = 25
filho_esq = true
pai.esq
No sucessor = no_sucessor(atual);
if (atual == root) root = sucessor;
else if (filho_esq) pai.esq = sucessor;
else pai.dir = sucessor;
sucessor.esq = atual.esq;
Trecho de código
1
2
3
4
5
sucessor
pai.esq = sucessor
Linha 3:
atual.esq
atual.item = 11
pai.item = 25
filho_esq = true
pai.esq
atual.esq
Trecho de código
1
2
3
4
5
pai.esq = sucessor
Linha 3:
sucessor
No sucessor = no_sucessor(atual);
if (atual == root) root = sucessor;
else if (filho_esq) pai.esq = sucessor;
else pai.dir = sucessor;
sucessor.esq = atual.esq;
pai.esq
atual.esq
Trecho de código
1
2
3
4
5
pai.esq= sucessor
Linha 3: Linha 5:
sucessor.esq =
atual.esq
sucessor sucessor
No sucessor = no_sucessor(atual);
if (atual == root) root = sucessor;
else if (filho_esq) pai.esq = sucessor;
else pai.dir = sucessor;
sucessor.esq = atual.esq;
public No no_sucessor(No apaga) {
No paidosucessor = apaga;
No sucessor = apaga;
No atual = apaga.dir;
while (atual != null) {
paidosucessor = sucessor;
sucessor = atual;
atual = atual.esq;
}
if (sucessor != apaga.dir) {
paidosucessor.esq = sucessor.dir;
sucessor.dir = apaga.dir;
}
return sucessor;
}
Método: no_sucessor
Vai para a sub-
arvore a direita
Caminha para o Nó
mais a esquerda
Se sucessor não é
o filho a direita do
Nó que deverá ser
eliminado
Pai herda os filhos
do sucessor que
sempre serão a
direita
Guardando a
referencia a direita
do sucessor para
quando ele
assumir a posição
correta na arvore
34
Método: caminhar
public void caminhar() {
System.out.print("n Exibindo em ordem: ");
inOrder(root);
System.out.print("n Exibindo em pos-ordem: ");
posOrder(root);
System.out.print("n Exibindo em pre-ordem: ");
preOrder(root);
System.out.print("n Altura da arvore: " + altura(root));
System.out.print("n Quantidade de folhas: " + folhas(root));
System.out.print("n Quantidade de Nós: " + contarNos(root));
if (root != null ) { // se arvore nao esta vazia
System.out.print("n Valor minimo: " + min().item);
System.out.println("n Valor maximo: " + max().item);
}
}
Chamada a métodos recursivos
Entrada: Não há
Saída: Não tem
35
Método: inOrder
public void inOrder(No atual) {
if (atual != null) {
inOrder(atual.esq);
System.out.print(atual.item + " ");
inOrder(atual.dir);
}
}
Primeiro visita o Nó a esquerda, depois a raiz (imprime o
item), finalizando com o Nó a direita.
Entrada: O Nó raiz
Saída: Não tem retorno
36
Método: posOrder
public void posOrder(No atual) {
if (atual != null) {
posOrder(atual.esq);
posOrder(atual.dir);
System.out.print(atual.item + " ");
}
}
Primeiro visita o Nó a esquerda, depois o Nó a direita,
finalizando com a raiz (imprime o item).
Entrada: O Nó raiz
Saída: Não tem retorno
37
Método: preOrder
public void preOrder(No atual) {
if (atual != null) {
System.out.print(atual.item + " ");
preOrder(atual.esq);
preOrder(atual.dir);
}
}
Primeiro visita a raiz (imprime o item), depois o Nó a
esquerda, finalizando com o Nó a direita.
Entrada: O Nó raiz
Saída: Não tem retorno
38
Método: folhas
public int folhas(No atual) {
if (atual == null) return 0;
if (atual.esq == null && atual.dir == null)
return 1;
return folhas(atual.esq) + folhas(atual.dir);
}
Entrada: O Nó raiz
Saída: Numero de folhas da arvore
39
Método: folhas
public int folhas(No atual) {
if (atual == null) return 0;
if (atual.esq == null && atual.dir == null)
return 1;
return folhas(atual.esq) + folhas(atual.dir);
}
Entrada: O Nó raiz
Saída: Numero de folhas da arvore
A arvore não possui itens ou chegou no final e não encontrou mais nenhum item
retorna zero
Retorne chamada recursiva da função contando a quantidade de folhas a
esquerda mais a direita da arvore
Se encontrou somente um item (raiz) ou chegou em uma folha,
retorna 1
40
Método: contarNos
public int contarNos(No atual) {
if (atual == null)
return 0;
else
return ( 1 + contarNos(atual.esq) +
contarNos(atual.dir) );
}
Entrada: O Nó raiz
Saída: Numero de Nós
Arvore vazia ou chegou no final e não encontrou mais nenhum item retorna zero
Senão retorne o valor 1 + chamada recursiva da função
contando a quantidade de nós a esquerda mais a direita da
arvore
41
Método: min
public No min() {
No atual = root;
No anterior = null;
while (atual != null) {
anterior = atual;
atual = atual.esq;
}
return anterior;
}
Entrada: não há
Saída: No mais a esquerda (Nó mínimo)
42
Método: min
public No min() {
No atual = root;
No anterior = null;
while (atual != null) {
anterior = atual;
atual = atual.esq;
}
return anterior;
}
Entrada: não há
Saída: No mais a esquerda (Nó mínimo)
Começa na raiz
Enquanto não encontrar um Nó
igual a null
Guarda o Nó anterior
Caminha para o filho a esquerda
43
Método: max
public No max() {
No atual = root;
No anterior = null;
while (atual != null) {
anterior = atual;
atual = atual.dir;
}
return anterior;
}
Entrada: não há
Saída: No mais a direita (Nó máximo)
44
Método: max
public No max() {
No atual = root;
No anterior = null;
while (atual != null) {
anterior = atual;
atual = atual.dir;
}
return anterior;
}
Entrada: não há
Saída: No mais a direita (Nó máximo)
Começa na raiz
Enquanto não encontrar um Nó
igual a null
Guarda o Nó anterior
Caminha para o filho a direita
Exemplo de uso da classe Tree:
class TreeBinApp {
public static void main(String[] args) {
Scanner le = new Scanner(System.in);
Tree arv = new Tree();
int opcao;
long x;
System.out.print("n Programa Arvore binaria de long");
do {
System.out.print("n***********************************");
System.out.print("nEntre com a opcao:");
System.out.print("n ----1: Inserir");
System.out.print("n ----2: Excluir");
System.out.print("n ----3: Pesquisar");
System.out.print("n ----4: Exibir");
System.out.print("n ----5: Sair do programa");
System.out.print("n***********************************");
System.out.print("n-> ");
opcao = le.nextInt();
switch(opcao) {
case 1: {
System.out.print("n Informe o valor (long) -> ");
x = le.nextLong();
x = le.nextLong();
arv.inserir(x);
break;
}
case 2: {
System.out.print("n Informe o valor (long) -> ");
x = le.nextLong();
if ( !arv.remover(x) )
System.out.print("n Valor nao encontrado!");;
break;
}
case 3: {
System.out.print("n Informe o valor (long) -> ");
x = le.nextLong();
if( arv.buscar(x) != null )
System.out.print("n Valor Encontrado");
else
System.out.print("n Valor nao encontrado!");
break;
}
case 4: {
arv.caminhar();
break;
}
} // fim switch
} while(opcao != 5);
}
}
https://gist.github.com/divanibarbosa/819e7cfcf1b9bae48c4e0f5bd74fb658
48
Atividades
1. No código Java para uma árvore, o ________ e a ________
são geralmente classes separadas.
.2. Uma sub-árvore de uma árvore binária sempre tem
(a) Uma raiz que é um filho da raiz da árvore principal
(b) Uma raiz não conectada a raiz da árvore principal
(c) Menos Nós que a árvore principal
(d) Uma irmã com mesmo número de Nós
3. Verdadeiro ou falso:
(a) Eliminar um Nó com um filho de uma árvore binária de busca envolve
encontrar o sucessor desse Nó.
(b) Nem todas as árvores são binárias.
(c) Uma árvore não balanceada é uma árvore na qual a raiz ou algum
outro Nó tenha muito mais filhos à esquerda do que filhos à direita ou
vice-versa.
49
Atividades
4. Trabalho 2 - Exercício 6. Desenhe uma arvore binária
usando a seguinte sequencia de dados de entrada:
(a) 25, 11, 42, 6, 19, 37 e 14
(b) 11, 22, 33, 44, -11, -33 e -22
(c) 14, 4, 15, 3, 9, 13, 18, 7, 11, 16, 20, 5, 17, 4 e 5
Responda: Quantas folhas, nós e qual a altura das arvores (a), (b) e (c).
Escreva a arvore (b) e (c) em pré-ordem e pós-ordem.
Desenhe as arvores (a), (b) e (c) depois da inserção do nó 21 e da
remoção do nó 11 para as arvores (a) e (b) e nó 18 para arvore (c).
5. Desenvolva um programa árvore binária de:
(a) double
(b) caracteres
(c) strings
50
Atividades
6. Desenvolva um programa árvore binária para um objeto
que represente uma agenda telefônica, use o nome como
campo chave

Aula 19

  • 1.
    Estrutura de Dados Implementação daArvore Binária profa. Divani Barbosa Aula 13 parte 2
  • 2.
    2 É uma estruturade dados caracterizada por:  Ou não tem elemento algum (árvore vazia).  Ou tem um elemento distinto, denominado raiz, com dois apontamentos para dois elos diferentes, denominadas sub- árvore esquerda e sub-árvore direita. Arvore Binária Exemplos: a) b)
  • 3.
  • 4.
    4 Arvores Balanceadas  Umaarvore é considerada balanceada quando suas sub- arvores a esquerda e a direita possuem a mesma altura.  A arvore não balanceada é definida como degenerada. Exemplos: arvore binária balanceada arvore binária degenerada a) b)
  • 5.
    5 Classe No Uma arvorebinária precisa de uma classe de objetos Nós, assim como vimos na lista duplamente encadeada: class No { public long item; public No esq; public No dir; } espaço para armazenamento da informação (chave) Um espaço para armazenar uma referência da localização na memória onde o Nó a esquerda se encontra. Um espaço para armazenar a referência do Nó a direita.
  • 6.
    6 Nó esq = dir = item= 14 Nó esq = dir = item = 4 Nó esq = dir = item = 16 Nó esq = NULL dir = NULL item = 3 Nó esq = NULL dir = NULL item = 9 Nó esq = NULL dir = NULL item = 15 Nó esq = NULL dir = NULL item = 18 As referencias são para outras sub-arvores root Elos de uma arvore binária
  • 7.
    7 Nó esq = dir = item= 14 Nó esq = dir = item = 4 Nó esq = dir = item = 16 Nó esq = NULL dir = NULL item = 3 Nó esq = NULL dir = NULL item = 9 Nó esq = NULL dir = NULL item = 15 Nó esq = NULL dir = NULL item = 18 root = null A árvore pode não ter nenhum elemento (árvore vazia) Elos de uma arvore binária
  • 8.
    8 Implementação private No root; ClasseTree: Campo Construtor public Tree() { root=null; } Métodos inserir: Insere itens na arvore buscar: Retorna Nó procurado ou null remover: Retorna verdadeiro se removeu item no_sucessor: Retorna o Nó sucessor ao passado no parâmetro caminhar: (inOrder, preOrder, posOrder, altura, folhas, min, max, contarNos)
  • 9.
    Método: inserir A inserçãocomeça com a chave sendo atribuida a raiz, logo após a função começa com uma busca, a-partir da raiz, comparando a chave com o valor da raiz. Se a chave é menor ou igual do que a raiz, ela é introduzida num novo nó a esquerda da raiz, ou na direita caso a chave seja maior que a raiz, e assim sucessivamente, item a item, os nós são criados. Exemplo: Itens a serem adicionados: 25, 11, 42, 6, 19, 37 e 14
  • 10.
    Método: inserir public voidinserir(long v) { No novo = new No(); novo.item = v; novo.dir = null; novo.esq = null; if (root == null) root = novo; else { // inserir aqui // trecho de código // para tratamento // caso árvore não vazia } } Entrada: item que deseja inserir Saída: não há Criando objeto Nó e armazenando na referencia novo se arvore vazia
  • 11.
    No atual =root; No anterior; while (true) { anterior = atual; if (v <= atual.item) { atual = atual.esq; if (atual == null) { anterior.esq = novo; return; } } else { atual = atual.dir; if (atual == null) { anterior.dir = novo; return; } } } // fim do laço while trecho de código para tratamento caso não raiz (arvore não vazia) começa a procurar desde raiz Adiciona a esquerda e sai Adiciona a direita e sai Caminha para esquerda Caminha para direita Guarda o Nó anterior
  • 12.
    12 Método: buscar public Nobuscar(long chave) { if (root == null) return null; No atual = root; while (atual.item != chave) { if (chave < atual.item ) atual = atual.esq; else atual = atual.dir; if (atual == null) return null; } return atual; } Entrada: chave Saída: Nó que procura ou null caso não encontre a chave começa a procurar desde raiz se arvore vazia enquanto nao encontrou caminha para esquerda caminha para direita encontrou uma folha -> sai Saiu do laço while e chegou aqui é porque encontrou item
  • 13.
    Método: remover O processode exclusão de um nó é o mais complexo. Para excluir um nó de uma árvore binária, deve-se considerar três casos distintos: Remoção da folha A exclusão de um nó que se encontra no fim da árvore, isto é, na folha, é o caso mais simples de exclusão. Basta remover o nó da árvore
  • 14.
    14 Remoção de umnó com “filho” Caso o nó que será excluído tenha um único "filho", o "avô" herda o "filho".
  • 15.
    15 Remoção de umnó com dois “filhos” Se o nó a ser excluído tiver dois "filhos", o processo de exclusão poderá operar de duas maneiras diferentes: Substituir o valor do nó a ser retirado pelo valor sucessor (o nó mais à esquerda da sub-árvore direita).
  • 16.
    Método: remover public booleanremover(long v) { if (root == null) return false; No atual = root; No pai = root; boolean filho_esq = true; while ( atual.item != v) { pai = atual; if ( v < atual.item ) { atual = atual.esq; filho_esq = true; } else { atual = atual.dir; filho_esq = false; } if (atual == null) return false; } // fim laço while busca Entrada: item que deseja remover Saída: verdadeiro ou falso Enquanto não encontrou Caminha a esquerda Caminha a direita Chegou em uma folha
  • 17.
    public boolean remover(longv) { if (root == null) return false; No atual = root; No pai = root; boolean filho_esq = true; while ( atual.item != v) { pai = atual; if ( v < atual.item ) { atual = atual.esq; filho_esq = true; } else { atual = atual.dir; filho_esq = false; } if (atual == null) return false; } // fim laço while busca Método: remover Entrada: item que deseja remover Saída: verdadeiro ou falso Se terminou o laço de busca sem sair do método remover quer dizer que:  Encontrou o valor (v)  "atual": contem a referencia ao No a ser eliminado  "pai": contem a referencia para o pai do No a ser eliminado  "filho_esq": é verdadeiro se atual é filho a esquerda do pai
  • 18.
    Método: remover Entrada: itemque deseja remover Saída: verdadeiro ou falso atual.item = pai.item = filho_esq = atual.item = 11 pai.item = 25 filho_esq = true public boolean remover(long v) { if (root == null) return false; No atual = root; No pai = root; boolean filho_esq = true; while ( atual.item != v) { pai = atual; if ( v < atual.item ) { atual = atual.esq; filho_esq = true; } else { atual = atual.dir; filho_esq = false; } if (atual == null) return false; } // fim laço while busca
  • 19.
    if (atual.esq ==null && atual.dir == null) { if (atual == root ) root = null; else if (filho_esq) pai.esq = null; else pai.dir = null; } Eliminando uma folha atual.item = 6 pai.item = 11 filho_esq = true Se não possui nenhum filho (é uma folha), elimine-o
  • 20.
    Se é paie não possui filho a direita atual.item = 19 pai.item = 11 filho_esq = false Substitui pela sub-árvore a direita else if (atual.dir == null) { if (atual == root) root = atual.esq; else if (filho_esq) pai.esq = atual.esq; else pai.dir = atual.esq; } pai.dir atual.esq
  • 21.
    Se é paie não possui filho a esquerda atual.item = 6 pai.item = 11 filho_esq = true Substitui pela sub-árvore a esquerda else if (atual.esq == null) { if (atual == root) root = atual.dir; else if (filho_esq) pai.esq = atual.dir; else pai.dir = atual.dir; } pai.esq atual.dir
  • 22.
    Se possui maisde um filho Se for um avô ou outro grau maior de parentesco else { No sucessor = no_sucessor(atual); if (atual == root) root = sucessor; else if (filho_esq) pai.esq = sucessor; else pai.dir = sucessor; sucessor.esq = atual.esq; } return true; // removeu item retorna true } // fim método remover Usando sucessor que seria a referencia ao Nó mais a esquerda da sub- árvore a direita do Nó que deseja-se remover
  • 23.
    No sucessor =no_sucessor(atual); if (atual == root) root = sucessor; else if (filho_esq) pai.esq = sucessor; else pai.dir = sucessor; sucessor.esq = atual.esq; Trecho de código atual.item = 11 pai.item = 25 filho_esq = true 1 2 3 4 5
  • 24.
    public No no_sucessor(Noapaga) { No paidosucessor = apaga; No sucessor = apaga; No atual = apaga.dir; while (atual != null) { paidosucessor = sucessor; sucessor = atual; atual = atual.esq; } if (sucessor != apaga.dir) { paidosucessor.esq = sucessor.dir; sucessor.dir = apaga.dir; } return sucessor; } Método: no_sucessor Retorno: apaga paisucessor sucessor atual Entrada:
  • 25.
    public No no_sucessor(Noapaga) { No paidosucessor = apaga; No sucessor = apaga; No atual = apaga.dir; while (atual != null) { paidosucessor = sucessor; sucessor = atual; atual = atual.esq; } if (sucessor != apaga.dir) { paidosucessor.esq = sucessor.dir; sucessor.dir = apaga.dir; } return sucessor; } Método: no_sucessor Retorno: apaga sucessor atual paisucessor sucessor atual Entrada: paisucessor
  • 26.
    public No no_sucessor(Noapaga) { No paidosucessor = apaga; No sucessor = apaga; No atual = apaga.dir; while (atual != null) { paidosucessor = sucessor; sucessor = atual; atual = atual.esq; } if (sucessor != apaga.dir) { paidosucessor.esq = sucessor.dir; sucessor.dir = apaga.dir; } return sucessor; } Método: no_sucessor Retorno: apaga sucessor atual paisucessor sucessor atual Entrada: paisucessor sucessor atual = null true
  • 27.
    public No no_sucessor(Noapaga) { No paidosucessor = apaga; No sucessor = apaga; No atual = apaga.dir; while (atual != null) { paidosucessor = sucessor; sucessor = atual; atual = atual.esq; } if (sucessor != apaga.dir) { paidosucessor.esq = sucessor.dir; sucessor.dir = apaga.dir; } return sucessor; } Método: no_sucessor Retorno: apaga sucessor atual paisucessor sucessor atual sucessor atual = null Entrada: true paisucessor sucessor
  • 28.
    public No no_sucessor(Noapaga) { No paidosucessor = apaga; No sucessor = apaga; No atual = apaga.dir; while (atual != null) { paidosucessor = sucessor; sucessor = atual; atual = atual.esq; } if (sucessor != apaga.dir) { paidosucessor.esq = sucessor.dir; sucessor.dir = apaga.dir; } return sucessor; } Método: no_sucessor Retorno: apaga sucessor atual paisucessor sucessor atual = null Entrada: true paisucessor sucessor null
  • 29.
    public No no_sucessor(Noapaga) { No paidosucessor = apaga; No sucessor = apaga; No atual = apaga.dir; while (atual != null) { paidosucessor = sucessor; sucessor = atual; atual = atual.esq; } if (sucessor != apaga.dir) { paidosucessor.esq = sucessor.dir; sucessor.dir = apaga.dir; } return sucessor; } Método: no_sucessor sucessor apaga paisucessor sucessor atual paisucessor sucessor atual = null Entrada: true null apaga.dir Retorno:
  • 30.
    atual.item = 11 pai.item= 25 filho_esq = true pai.esq No sucessor = no_sucessor(atual); if (atual == root) root = sucessor; else if (filho_esq) pai.esq = sucessor; else pai.dir = sucessor; sucessor.esq = atual.esq; Trecho de código 1 2 3 4 5 sucessor pai.esq = sucessor Linha 3: atual.esq
  • 31.
    atual.item = 11 pai.item= 25 filho_esq = true pai.esq atual.esq Trecho de código 1 2 3 4 5 pai.esq = sucessor Linha 3: sucessor No sucessor = no_sucessor(atual); if (atual == root) root = sucessor; else if (filho_esq) pai.esq = sucessor; else pai.dir = sucessor; sucessor.esq = atual.esq;
  • 32.
    pai.esq atual.esq Trecho de código 1 2 3 4 5 pai.esq=sucessor Linha 3: Linha 5: sucessor.esq = atual.esq sucessor sucessor No sucessor = no_sucessor(atual); if (atual == root) root = sucessor; else if (filho_esq) pai.esq = sucessor; else pai.dir = sucessor; sucessor.esq = atual.esq;
  • 33.
    public No no_sucessor(Noapaga) { No paidosucessor = apaga; No sucessor = apaga; No atual = apaga.dir; while (atual != null) { paidosucessor = sucessor; sucessor = atual; atual = atual.esq; } if (sucessor != apaga.dir) { paidosucessor.esq = sucessor.dir; sucessor.dir = apaga.dir; } return sucessor; } Método: no_sucessor Vai para a sub- arvore a direita Caminha para o Nó mais a esquerda Se sucessor não é o filho a direita do Nó que deverá ser eliminado Pai herda os filhos do sucessor que sempre serão a direita Guardando a referencia a direita do sucessor para quando ele assumir a posição correta na arvore
  • 34.
    34 Método: caminhar public voidcaminhar() { System.out.print("n Exibindo em ordem: "); inOrder(root); System.out.print("n Exibindo em pos-ordem: "); posOrder(root); System.out.print("n Exibindo em pre-ordem: "); preOrder(root); System.out.print("n Altura da arvore: " + altura(root)); System.out.print("n Quantidade de folhas: " + folhas(root)); System.out.print("n Quantidade de Nós: " + contarNos(root)); if (root != null ) { // se arvore nao esta vazia System.out.print("n Valor minimo: " + min().item); System.out.println("n Valor maximo: " + max().item); } } Chamada a métodos recursivos Entrada: Não há Saída: Não tem
  • 35.
    35 Método: inOrder public voidinOrder(No atual) { if (atual != null) { inOrder(atual.esq); System.out.print(atual.item + " "); inOrder(atual.dir); } } Primeiro visita o Nó a esquerda, depois a raiz (imprime o item), finalizando com o Nó a direita. Entrada: O Nó raiz Saída: Não tem retorno
  • 36.
    36 Método: posOrder public voidposOrder(No atual) { if (atual != null) { posOrder(atual.esq); posOrder(atual.dir); System.out.print(atual.item + " "); } } Primeiro visita o Nó a esquerda, depois o Nó a direita, finalizando com a raiz (imprime o item). Entrada: O Nó raiz Saída: Não tem retorno
  • 37.
    37 Método: preOrder public voidpreOrder(No atual) { if (atual != null) { System.out.print(atual.item + " "); preOrder(atual.esq); preOrder(atual.dir); } } Primeiro visita a raiz (imprime o item), depois o Nó a esquerda, finalizando com o Nó a direita. Entrada: O Nó raiz Saída: Não tem retorno
  • 38.
    38 Método: folhas public intfolhas(No atual) { if (atual == null) return 0; if (atual.esq == null && atual.dir == null) return 1; return folhas(atual.esq) + folhas(atual.dir); } Entrada: O Nó raiz Saída: Numero de folhas da arvore
  • 39.
    39 Método: folhas public intfolhas(No atual) { if (atual == null) return 0; if (atual.esq == null && atual.dir == null) return 1; return folhas(atual.esq) + folhas(atual.dir); } Entrada: O Nó raiz Saída: Numero de folhas da arvore A arvore não possui itens ou chegou no final e não encontrou mais nenhum item retorna zero Retorne chamada recursiva da função contando a quantidade de folhas a esquerda mais a direita da arvore Se encontrou somente um item (raiz) ou chegou em uma folha, retorna 1
  • 40.
    40 Método: contarNos public intcontarNos(No atual) { if (atual == null) return 0; else return ( 1 + contarNos(atual.esq) + contarNos(atual.dir) ); } Entrada: O Nó raiz Saída: Numero de Nós Arvore vazia ou chegou no final e não encontrou mais nenhum item retorna zero Senão retorne o valor 1 + chamada recursiva da função contando a quantidade de nós a esquerda mais a direita da arvore
  • 41.
    41 Método: min public Nomin() { No atual = root; No anterior = null; while (atual != null) { anterior = atual; atual = atual.esq; } return anterior; } Entrada: não há Saída: No mais a esquerda (Nó mínimo)
  • 42.
    42 Método: min public Nomin() { No atual = root; No anterior = null; while (atual != null) { anterior = atual; atual = atual.esq; } return anterior; } Entrada: não há Saída: No mais a esquerda (Nó mínimo) Começa na raiz Enquanto não encontrar um Nó igual a null Guarda o Nó anterior Caminha para o filho a esquerda
  • 43.
    43 Método: max public Nomax() { No atual = root; No anterior = null; while (atual != null) { anterior = atual; atual = atual.dir; } return anterior; } Entrada: não há Saída: No mais a direita (Nó máximo)
  • 44.
    44 Método: max public Nomax() { No atual = root; No anterior = null; while (atual != null) { anterior = atual; atual = atual.dir; } return anterior; } Entrada: não há Saída: No mais a direita (Nó máximo) Começa na raiz Enquanto não encontrar um Nó igual a null Guarda o Nó anterior Caminha para o filho a direita
  • 45.
    Exemplo de usoda classe Tree: class TreeBinApp { public static void main(String[] args) { Scanner le = new Scanner(System.in); Tree arv = new Tree(); int opcao; long x; System.out.print("n Programa Arvore binaria de long"); do { System.out.print("n***********************************"); System.out.print("nEntre com a opcao:"); System.out.print("n ----1: Inserir"); System.out.print("n ----2: Excluir"); System.out.print("n ----3: Pesquisar"); System.out.print("n ----4: Exibir"); System.out.print("n ----5: Sair do programa"); System.out.print("n***********************************"); System.out.print("n-> "); opcao = le.nextInt(); switch(opcao) { case 1: { System.out.print("n Informe o valor (long) -> "); x = le.nextLong();
  • 46.
    x = le.nextLong(); arv.inserir(x); break; } case2: { System.out.print("n Informe o valor (long) -> "); x = le.nextLong(); if ( !arv.remover(x) ) System.out.print("n Valor nao encontrado!");; break; } case 3: { System.out.print("n Informe o valor (long) -> "); x = le.nextLong(); if( arv.buscar(x) != null ) System.out.print("n Valor Encontrado"); else System.out.print("n Valor nao encontrado!"); break; } case 4: { arv.caminhar(); break; }
  • 47.
    } // fimswitch } while(opcao != 5); } } https://gist.github.com/divanibarbosa/819e7cfcf1b9bae48c4e0f5bd74fb658
  • 48.
    48 Atividades 1. No códigoJava para uma árvore, o ________ e a ________ são geralmente classes separadas. .2. Uma sub-árvore de uma árvore binária sempre tem (a) Uma raiz que é um filho da raiz da árvore principal (b) Uma raiz não conectada a raiz da árvore principal (c) Menos Nós que a árvore principal (d) Uma irmã com mesmo número de Nós 3. Verdadeiro ou falso: (a) Eliminar um Nó com um filho de uma árvore binária de busca envolve encontrar o sucessor desse Nó. (b) Nem todas as árvores são binárias. (c) Uma árvore não balanceada é uma árvore na qual a raiz ou algum outro Nó tenha muito mais filhos à esquerda do que filhos à direita ou vice-versa.
  • 49.
    49 Atividades 4. Trabalho 2- Exercício 6. Desenhe uma arvore binária usando a seguinte sequencia de dados de entrada: (a) 25, 11, 42, 6, 19, 37 e 14 (b) 11, 22, 33, 44, -11, -33 e -22 (c) 14, 4, 15, 3, 9, 13, 18, 7, 11, 16, 20, 5, 17, 4 e 5 Responda: Quantas folhas, nós e qual a altura das arvores (a), (b) e (c). Escreva a arvore (b) e (c) em pré-ordem e pós-ordem. Desenhe as arvores (a), (b) e (c) depois da inserção do nó 21 e da remoção do nó 11 para as arvores (a) e (b) e nó 18 para arvore (c). 5. Desenvolva um programa árvore binária de: (a) double (b) caracteres (c) strings
  • 50.
    50 Atividades 6. Desenvolva umprograma árvore binária para um objeto que represente uma agenda telefônica, use o nome como campo chave