Post on 22-Apr-2015
Prof. Hilton Cardoso Marins Juniorhiltonmarins@gmail.com
ÁRVORES BINÁRIAS
Árvores Binárias
São estruturas do tipo árvore, onde o grau de cada nó é menor ou igual a 2.
Quando o grau do nó for igual a 2 temos a subárvore a direita (sad) e a subárvore a esquerda (sae), quando o grau do nó for igual a 1 temos uma subárvore direita ou uma subárvore esquerda e se o grau do nó for igual a 0 não temos subárvores.
Aplicação:
Representação de expressões aritméticas de tal forma que a hierarquia dos operadores fique clara.
Em operações de ordenação.
Exemplo de Árvore Binária
A expressão (a * b) + (c / (d + e)) poderia ser representada da seguinte forma:
+
:*
ba +c
ed
Definição
Uma árvore binária T é um conjunto finito de elementos denominados nós ou vértices, tal que:
T = Ø e a árvore é dita vazia, ou
Existe um nó especial r, chamado raiz de T, e os restantes podem ser divididos em dois subconjuntos disjuntos, Tr
L e Tr
R a subárvore esquerda e a direita de r,respectivamente, as quais são também
árvores binárias.
Tipos de Árvores Binárias Árvore estritamente binária:
Cada nó possui 0 ou 2 filhos.
Árvore binária completa:Se v é um nó tal que alguma subárvore de v é
vazia, então v se localiza ou no último (maior) ou no penúltimo nível da árvore.
Árvore binária cheia:Se v é um nó tal que alguma subárvore de v é
vazia, então v se localiza no último (maior) nível da árvore. v é um nó folha.
Árvore Binária
Em uma árvore binária cheia o número de nós do nível i é igual a 2i.
Consequentemente, em qualquer árvore binária existe no máximo 2i nós no nível i.
20 = 1
21 = 2
22 = 4
23 = 8
Representação de uma Árvore Binária por Contiguidade
O nó será uma estrutura com um campo de informação e duas referências, uma para a sae (subárvore esquerda) e outra para a sad (subárvore direita).
A Raiz localiza-se na primeira célula (índice 0)
-1 indica filho nuloÍndice Informação sae sad
0 13 4 2
1 31 6 -1
2 25 7 1
3 12 -1 -1
4 10 5 3
5 2 -1 -1
6 29 -1 -1
7 20 -1 -1
13
10 25
3112 202
29
Representação de uma Árvore Binária por Encadeamento
O nó é formado por uma estrutura composta de:
Campo de informaçãoPonteiro para sae.
Ponteiro para sad.sae info sad
A
sae info sad
B null
sae info sad
C
sae info sad
null D
sae info sad
E
sae info sad
null F null
sae info sad
null H null
sae info sad
null I null
sae info sad
null G null
Operações com Árvore Binária por Encadeamento
Para exemplificarmos operações com uma árvore binária por encadeamento utilizaremos a definição abaixo:
struct TipoArvore { int info; struct TipoArvore* sae; struct TipoArvore* sad;};
typedef struct TipoArvore Arvore;
Trata-se de uma árvore binária encadeada de números inteiros, todos os exemplos podem ser adaptados para qualquer outro tipo de dado básico ou estruturado.
Operações com Árvore Binária por Encadeamento
//cria uma árvore vaziaArvore* inicializa();
//verifica se a arvore está vaziaint estaVazia(Arvore* a);
//cria um nó, dado a informação e as duas subárvoresArvore* criaNo(int n, Arvore* sae, Arvore* sad);
//libera a estrutura da árvoreArvore* libera(Arvore* a);
//Determinar se uma informação se encontra ou não na árvoreint busca(Arvore* a, int n);
//imprime a informação de todos os nós da árvorevoid imprime(Arvore* a);
//Determinar a altura de uma árvoreint getAltura(Arvore* a);
//Contar quantas são as folhas de uma árvoreint getfolhas(Arvore* a);
O programa principalint main(){ Arvore *D = criaNo(4, inicializa(), inicializa()); Arvore *E = criaNo(5, inicializa(), inicializa()); Arvore *F = criaNo(6, inicializa(), inicializa()); Arvore *G = criaNo(7, inicializa(), inicializa()); Arvore *B = criaNo(2, D, E); Arvore *C = criaNo(3, F, G); Arvore *A = criaNo(1, B, C);
imprime(A);
printf("\nAltura da arvore = %d", getAltura(A));
if (!busca(A, 113)){ printf("\nInformacao INEXISTENTE!"); }else{ printf("\nInformacao ENCONTRADA COM SUCESSO!"); }
printf("\nQuantidade de folhas = %d", getFolhas(A));
A = libera(A); imprime(A); return 0;}
1, 2, 4, 5, 3, 6 e 7
2
4
Não haverá saída!
Analisando a chamada da função main:
Arvore *D = criaNo(4, inicializa(), inicializa());
/* cria uma árvore vazia. */Arvore* inicializa(){ return NULL;}
/* cria um nó com a informação, a sae e a sad. */Arvore* criaNo(int n, Arvore* sae, Arvore* sad){ Arvore* p = (Arvore*) malloc(sizeof(Arvore)); p->info = n; p->sae = sae; p->sad = sad; return p;}
nullnull
Analisando a chamada da função main:
Arvore *D = criaNo(4, inicializa(), inicializa());
/* cria uma árvore vazia. */Arvore* inicializa(){ return NULL;}
/* cria um nó com a informação, a sae e a sad. */Arvore* criaNo(int n, Arvore* sae, Arvore* sad){ Arvore* p = (Arvore*) malloc(sizeof(Arvore)); p->info = n; p->sae = sae; p->sad = sad; return p;}
sae info sad
nullnull
p
Analisando a chamada da função main:
Arvore *D = criaNo(4, inicializa(), inicializa());
/* cria uma árvore vazia. */Arvore* inicializa(){ return NULL;}
/* cria um nó com a informação, a sae e a sad. */Arvore* criaNo(int n, Arvore* sae, Arvore* sad){ Arvore* p = (Arvore*) malloc(sizeof(Arvore)); p->info = n; p->sae = sae; p->sad = sad; return p;}
nullnull
sae info sad
null 4 null
p
Analisando a chamada da função main:
Arvore *D = criaNo(4, inicializa(), inicializa());
/* cria uma árvore vazia. */Arvore* inicializa(){ return NULL;}
/* cria um nó com a informação, a sae e a sad. */Arvore* criaNo(int n, Arvore* sae, Arvore* sad){ Arvore* p = (Arvore*) malloc(sizeof(Arvore)); p->info = n; p->sae = sae; p->sad = sad; return p;}
nullnull
sae info sad
null 4 null
D
Analisando a chamada da função main:
Arvore *E = criaNo(5, inicializa(), inicializa());
/* cria um nó com a informação, a sae e a sad. */Arvore* criaNo(int n, Arvore* sae, Arvore* sad){ Arvore* p = (Arvore*) malloc(sizeof(Arvore)); p->info = n; p->sae = sae; p->sad = sad; return p;}
sae info sad
null 4 null
D
sae info sad
null 5 null
E
Analisando a chamada da função main:
Arvore *F = criaNo(6, inicializa(), inicializa());
/* cria um nó com a informação, a sae e a sad. */Arvore* criaNo(int n, Arvore* sae, Arvore* sad){ Arvore* p = (Arvore*) malloc(sizeof(Arvore)); p->info = n; p->sae = sae; p->sad = sad; return p;}
sae info sad
null 4 null
D
sae info sad
null 5 null
E
sae info sad
null 6 null
F
Analisando a chamada da função main:
Arvore *G = criaNo(7, inicializa(), inicializa());
/* cria um nó com a informação, a sae e a sad. */Arvore* criaNo(int n, Arvore* sae, Arvore* sad){ Arvore* p = (Arvore*) malloc(sizeof(Arvore)); p->info = n; p->sae = sae; p->sad = sad; return p;}
sae info sad
null 4 null
D
sae info sad
null 5 null
E
sae info sad
null 6 null
F
sae info sad
null 7 null
G
Analisando a chamada da função main:
Arvore *B = criaNo(2, D, E);
/* cria um nó com a informação, a sae e a sad. */Arvore* criaNo(int n, Arvore* sae, Arvore* sad){ Arvore* p = (Arvore*) malloc(sizeof(Arvore)); p->info = n; p->sae = sae; p->sad = sad; return p;}
sae info sad
null 4 null
D
sae info sad
null 5 null
E
sae info sad
null 6 null
F
sae info sad
null 7 null
G
Analisando a chamada da função main:
Arvore *B = criaNo(2, D, E);
/* cria um nó com a informação, a sae e a sad. */Arvore* criaNo(int n, Arvore* sae, Arvore* sad){ Arvore* p = (Arvore*) malloc(sizeof(Arvore)); p->info = n; p->sae = sae; p->sad = sad; return p;}
sae info sad
null 4 null
D
sae info sad
null 5 null
E
sae info sad
null 6 null
F
sae info sad
null 7 null
G
sae info sad
null null
p
Analisando a chamada da função main:
Arvore *B = criaNo(2, D, E);
/* cria um nó com a informação, a sae e a sad. */Arvore* criaNo(int n, Arvore* sae, Arvore* sad){ Arvore* p = (Arvore*) malloc(sizeof(Arvore)); p->info = n; p->sae = sae; p->sad = sad; return p;}
sae info sad
null 4 null
sae info sad
null 5 null
sae info sad
null 6 null
F
sae info sad
null 7 null
Gsae info sad
2
p
D E
Analisando a chamada da função main:
Arvore *B = criaNo(2, D, E);
/* cria um nó com a informação, a sae e a sad. */Arvore* criaNo(int n, Arvore* sae, Arvore* sad){ Arvore* p = (Arvore*) malloc(sizeof(Arvore)); p->info = n; p->sae = sae; p->sad = sad; return p;}
sae info sad
null 6 null
F
sae info sad
null 7 null
G
sae info sad
null 4 null
sae info sad
null 5 null
sae info sad
2
B
D E
Analisando a chamada da função main:
Arvore *C = criaNo(3, F, G);
/* cria um nó com a informação, a sae e a sad. */Arvore* criaNo(int n, Arvore* sae, Arvore* sad){ Arvore* p = (Arvore*) malloc(sizeof(Arvore)); p->info = n; p->sae = sae; p->sad = sad; return p;}
sae info sad
null 6 null
F
sae info sad
null 7 null
G
sae info sad
null 4 null
sae info sad
null 5 null
sae info sad
2
B
D E
Analisando a chamada da função main:
Arvore *C = criaNo(3, F, G);
/* cria um nó com a informação, a sae e a sad. */Arvore* criaNo(int n, Arvore* sae, Arvore* sad){ Arvore* p = (Arvore*) malloc(sizeof(Arvore)); p->info = n; p->sae = sae; p->sad = sad; return p;}
sae info sad
null 6 null
F
sae info sad
null 7 null
G
sae info sad
null 4 null
sae info sad
null 5 null
sae info sad
2
B
D E
sae info sad
null null
p
Analisando a chamada da função main:
Arvore *C = criaNo(3, F, G);
/* cria um nó com a informação, a sae e a sad. */Arvore* criaNo(int n, Arvore* sae, Arvore* sad){ Arvore* p = (Arvore*) malloc(sizeof(Arvore)); p->info = n; p->sae = sae; p->sad = sad; return p;}
sae info sad
null 6 null
F
sae info sad
null 7 null
G
sae info sad
null 4 null
sae info sad
null 5 null
sae info sad
2
B
D Esae info sad
3
p
Analisando a chamada da função main:
Arvore *C = criaNo(3, F, G);
/* cria um nó com a informação, a sae e a sad. */Arvore* criaNo(int n, Arvore* sae, Arvore* sad){ Arvore* p = (Arvore*) malloc(sizeof(Arvore)); p->info = n; p->sae = sae; p->sad = sad; return p;}
sae info sad
null 6 null
F
sae info sad
null 7 null
G
sae info sad
null 4 null
sae info sad
null 5 null
sae info sad
2
B
D Esae info sad
3
C
Analisando a chamada da função main:
Arvore *A = criaNo(1, B, C);
/* cria um nó com a informação, a sae e a sad. */Arvore* criaNo(int n, Arvore* sae, Arvore* sad){ Arvore* p = (Arvore*) malloc(sizeof(Arvore)); p->info = n; p->sae = sae; p->sad = sad; return p;}
sae info sad
null 6 null
F
sae info sad
null 7 null
G
sae info sad
null 4 null
sae info sad
null 5 null
sae info sad
2
B
D Esae info sad
3
C
Analisando a chamada da função main:
Arvore *A = criaNo(1, B, C);
/* cria um nó com a informação, a sae e a sad. */Arvore* criaNo(int n, Arvore* sae, Arvore* sad){ Arvore* p = (Arvore*) malloc(sizeof(Arvore)); p->info = n; p->sae = sae; p->sad = sad; return p;}
sae info sad
null 6 null
F
sae info sad
null 7 null
G
sae info sad
null 4 null
sae info sad
null 5 null
sae info sad
2
B
D Esae info sad
3
C
sae info sad
null null
p
Analisando a chamada da função main:
Arvore *A = criaNo(1, B, C);
/* cria um nó com a informação, a sae e a sad. */Arvore* criaNo(int n, Arvore* sae, Arvore* sad){ Arvore* p = (Arvore*) malloc(sizeof(Arvore)); p->info = n; p->sae = sae; p->sad = sad; return p;}
sae info sad
null 6 null
F
sae info sad
null 7 null
G
sae info sad
null 4 null
sae info sad
null 5 null
sae info sad
2
B
D Esae info sad
3
C
sae info sad
1
p
Analisando a chamada da função main:
Arvore *A = criaNo(1, B, C);
/* cria um nó com a informação, a sae e a sad. */Arvore* criaNo(int n, Arvore* sae, Arvore* sad){ Arvore* p = (Arvore*) malloc(sizeof(Arvore)); p->info = n; p->sae = sae; p->sad = sad; return p;}
sae info sad
null 6 null
F
sae info sad
null 7 null
G
sae info sad
null 4 null
sae info sad
null 5 null
sae info sad
2
B
D Esae info sad
3
C
sae info sad
1
A
Configuração da Árvore até o momento
sae info sad
null 6 null
F
sae info sad
null 7 null
G
sae info sad
null 4 null
sae info sad
null 5 null
sae info sad
2
B
D Esae info sad
3
C
sae info sad
1
A
1
2 3
75 64
Exemplo
Usando as funções inicializa() e criaNo(), crie uma estrutura que represente a seguinte árvore:
1
2 3
64 5
Exemplo
Usando as funções inicializa() e criaNo(), crie uma estrutura que represente a seguinte árvore:
Arvore *D = criaNo(4, inicializa(), inicializa());Arvore *E = criaNo(5, inicializa(), inicializa());Arvore *F = criaNo(6, inicializa(), inicializa());Arvore *B = criaNo(2, inicializa(), D);Arvore *C = criaNo(3, E, F);Arvore *A = criaNo(1, B, C);
1
2 3
64 5
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
1, 2, 4, 5, 3, 6 e 7
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
a
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
/* verifica se a arvore está vazia. */int estaVazia(Arvore* a){ return a == NULL;}
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
a
1
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
a
1
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
a
1 2
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
a
1 2
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
a
1 2 4
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
a
1 2 4
null
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
a
1 2 4
null
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
a
1 2 4
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
1 2 4
a
null
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
1 2 4
a
null
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
1 2 4
a
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
1 2 4
a
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
1 2 4
a
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
1 2 4
a
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
1 2 4 5
a
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
1 2 4 5
a
null
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
1 2 4 5
a
null
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
1 2 4 5
a
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
1 2 4 5
a
null
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
1 2 4 5
a
null
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
1 2 4 5
a
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
1 2 4 5
a
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
1 2 4 5
a
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
1 2 4 5
a
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
1 2 4 5
a
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
1 2 4 5
a
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
1 2 4 5 3
a
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
1 2 4 5 3
a
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
1 2 4 5 3 6
a
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
1 2 4 5 3 6
a
null
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
1 2 4 5 3 6
a
null
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
1 2 4 5 3 6
a
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
1 2 4 5 3 6
a
null
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
1 2 4 5 3 6
a
null
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
1 2 4 5 3 6
a
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
1 2 4 5 3 6
a
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
1 2 4 5 3 6
a
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
1 2 4 5 3 6
a
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
1 2 4 5 3 6 7
a
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
1 2 4 5 3 6 7
a
null
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
1 2 4 5 3 6 7
a
null
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
1 2 4 5 3 6 7
a
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
1 2 4 5 3 6 7
a
null
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
1 2 4 5 3 6 7
a
null
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
1 2 4 5 3 6 7
a
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
1 2 4 5 3 6 7
a
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
1 2 4 5 3 6 7
a
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
1 2 4 5 3 6 7
a
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
1 2 4 5 3 6 7
a
Analisando a chamada da função main:
imprime(A);
/* imprime a informação de todos os nós da árvore. */void imprime(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprime(a->sae); /* mostra sae */ imprime(a->sad); /* mostra sad */ }}
1
2 3
75 64
1 2 4 5 3 6 7
a
Fim! Volta para a chamada externa.
Percurso em Árvores Binárias
Uma das operações básicas relativas à manipulação de árvores é a visita sistemática a cada um dos seus nós.
Para percorrer a árvore deve-se, então, visitar cada um de seus nós. Visitar um nó significa operar com a informação do nó. Por exemplo: imprimir (conforme analisado anteriormente), atualizar informações, etc.
Percurso em Árvores Binárias
Temos duas categorias de percurso:
Percurso em profundidade: Corresponde a visitar um nó raiz e explora tanto quanto possível cada um dos seus
ramos, antes de retroceder.
Percurso em largura: Corresponde a visitar cada nó começando o nível mais baixo (ou mais alto) e movendo para baixo (ou para cima) nível a nível, visitando nós em cada nível da esquerda para direita (ou da direita para a esquerda).
Percurso em Profundidade
Pré-ordem:
Visitar a raizPercorrer a sub-árvore esquerda em pré-
ordemPercorrer a sub-árvore direita em pré-ordem
In-ordem:
Percorrer a sub-árvore esquerda em in-ordemVisitar a raizPercorrer a sub-árvore direita em in-ordem
Pós-ordem:
Percorrer a sub-árvore esquerda em pós-ordem
Percorrer a sub-árvore direita em pós-ordem Visitar a raiz
Percurso em Profundidade: Pré-Ordem
Visitar a raizPercorrer a sub-árvore esquerda em pré-
ordemPercorrer a sub-árvore direita em pré-ordem
Percurso: A B D G C E H I F
* A função Imprime analisada anteriormente usou o percurso Pré-Ordem.
A
B C
F
G
ED
IH
Percurso em Profundidade: Pré-Ordem
Visitar a raizPercorrer a sub-árvore esquerda em pré-
ordemPercorrer a sub-árvore direita em pré-ordem
/* imprime todos os nós da árvore em Pre-Ordem. */void imprimePre(Arvore* a){ if(!estaVazia(a)){ printf("%d ", a->info); /* mostra raiz */ imprimePre(a->sae); /* mostra sae */ imprimePre(a->sad); /* mostra sad */ }}
Percurso em Profundidade: In-Ordem
Percorrer a sub-árvore esquerda em in-ordemVisitar a raizPercorrer a sub-árvore direita em in-ordem
Percurso: D G B A H E I C F
A
B C
F
G
ED
IH
Percurso em Profundidade: In-Ordem
Percorrer a sub-árvore esquerda em in-ordemVisitar a raizPercorrer a sub-árvore direita em in-ordem
/* imprime todos os nós da árvore em In-Ordem. */void imprimeIn(Arvore* a){ if(!estaVazia(a)){ imprimeIn(a->sae); /* mostra sae */ printf("%d ", a->info); /* mostra raiz */ imprimeIn(a->sad); /* mostra sad */ }}
Percurso em Profundidade: Pós-Ordem
Percorrer a sub-árvore esquerda em pós-ordem
Percorrer a sub-árvore direita em pós-ordem Visitar a raiz
Percurso: G D B H I E F C A
A
B C
F
G
ED
IH
Percurso em Profundidade: Pós-Ordem
Percorrer a sub-árvore esquerda em pós-ordem
Percorrer a sub-árvore direita em pós-ordem Visitar a raiz
/* imprime todos os nós da árvore em Pos-Ordem. */void imprimePos(Arvore* a){ if(!estaVazia(a)){ imprimePos(a->sae); /* mostra sae */ imprimePos(a->sad); /* mostra sad */ printf("%d ", a->info); /* mostra raiz */ }}
Exercícios de Percurso em Profundidade
1. Usando as funções inicializa() e criaNo(), crie uma estrutura que represente a seguinte árvore:
2. Indique o percurso em pré-ordem, in-ordem e pós-ordem.
20
10 30
96 1814
25 338 15
Exercícios de Percurso em Profundidade
Arvore *H = criaNo(6, inicializa(), inicializa());Arvore *I = criaNo(9, inicializa(), inicializa());Arvore *J = criaNo(14, inicializa(), inicializa());Arvore *K = criaNo(18, inicializa(), inicializa());Arvore *D = criaNo(8, H, I);Arvore *E = criaNo(15, J, K);Arvore *F = criaNo(25, inicializa(), inicializa());Arvore *G = criaNo(33, inicializa(), inicializa());Arvore *B = criaNo(10, D, E);Arvore *C = criaNo(30, F, G);Arvore *A = criaNo(20, B, C);
Pré-Ordem:20, 10, 8, 6, 9, 15, 14, 18, 30, 25 e 33In-Ordem: 6, 8, 9, 10, 14, 15, 18, 20, 25, 30 e 33.Pós-Ordem:6, 9, 8, 14, 18, 15, 10, 25, 33, 30 e 20.
20
10 30
96 1814
25 338 15
Percurso em Largura
Lembando: Corresponde a visitar cada nó começando o nível mais baixo (ou mais alto) e movendo para baixo (ou para cima) nível a nível, visitando nós em cada nível da esquerda para direita (ou da direita para a esquerda).
Percurso: A, B, C, D, E, F, G, H e I
A
B C
F
G
ED
IH
Percurso em Largura
Para exemplificar, o percurso será de cima para baixo e da esquerda para direita usando uma fila:
Quando um nó é visitado, seus filhos (se houver) são colocados no final da fila.
Nó no início da fila é visitado.
A
B C
F
G
ED
IH
Percurso em Largura
A B C
B C C D
C D D E F
Visita A – insere B e C na fila
Visita B – insere D na fila
Visita C – insere E e F na fila
E F GVisita D – insere G na filaD E F
F G H IVisita E – insere H e I na filaE F G
G H IVisita F F G H I
G H I Visita G H I
H I Visita H I
I Visita I
A
B C
F
G
ED
IH
FILA FILA