Você está na página 1de 66

Árvores

Prof. Bruno Kimura


DMC/ICE/UNIFEI
• Antes de iniciarmos ...
– Seria interessante ter alguma noção de
complexidade de algoritmos
Notação Big “O” (“O”Grande)
(Complexidade de Algoritmos)
Notação Nome Exemplo
Melhor O(1) Constante Acesso a uma posição de um vetor. Estruturas
condicionais.
O(log n) Logarítmica busca binária: encontrar um item em um vetor
ordenado, ou em uma árvore balanceada
O(n) Linear Encontrar um item em um vetor não ordenado.
O(n log n) Loglinear Ordenação em vetor (quick_sort, heap_sort,
merge_sort)
O(n^2) Quadrática Operação em dados multidimensionais
(matrizes)
O(n^c), C > 1 Polinomial Operação em dados multidimensionais
(matrizes)
O(c^n), C > 1 Exponencial Encontrar a solução para o “Caixeiro Viajante”
utilizando métodos de “dividir para conquistar”.
Pior
O(n!) Fatorial Encontrar a solução para o “Caixeiro Viajante”
utilizando métodos de “força bruta”.
Aplicação (Pra que serve?)
• Uma árvore é uma estrutura de dados útil
para representar relações de hierarquia e
dependência, bem como agrupamentos.
• Otimização em busca
Busca ...
• Considere o seguinte cenário:
– um vetor x de comprimento n, onde x é uma
estrutura não ordenada
15 6 7 18 3 13 2 9 4 17 20

– uma chave de busca k


– uma função de busca sequêncial f(k).
• Problema:
– Deseja-se encontrar k em x.
f(k): Busca Sequêncial

int f(int *x, int n, int k)


{
int i;
for(i=0; i<n; i++)
if (x[i] == k)
return i;
return(-1);
}
f(k): Busca Sequêncial
• Considerando x com n = 11 elementos não
ordenados:
15 6 7 18 3 13 2 9 4 17 20

• Pior caso:

• Melhor caso:
f(k): Busca Sequêncial
• Considerando x com n = 11 elementos não
ordenados:
15 6 7 18 3 13 2 9 4 17 20

• Pior caso: O(n)


– Haverá n comparações quando k==x[n-1] ou k não
existir em x
• Melhor caso: O(1)
– Haverá apenas 1 comparação se k == x[1]
f(k): Busca Sequêncial
• Problema:
– Se n for muito grande e, ainda, k estiver no pior
caso, como melhorar o desempenho na busca?
f(k): Busca Sequêncial
• Problema:
– Se n for muito grande e, ainda, k estiver no pior
caso, como melhorar o desempenho na busca?
• Árvores Binárias de Busca
f(k): Busca Sequêncial
• Problema:
– Se n for muito grande e, ainda, k estiver no pior
caso, como melhorar o desempenho na busca?
• Árvores Binárias de Busca: O(log n)

15 6 7 18 3 13 2 9 4 17 20

O número de comparações pode ser reduzido usando-se


uma árvore binária de busca.
Árvores
• Antes de saber o que são árvores binárias de
busca é necessário saber:
– O que são árvores
– O que são árvores binárias
Árvores
• Uma árvore T é um conjunto finito de
elementos denominados nós ou vértices tais
que:
– Se T = 0, então a árvore é dita vazia
– Se T > 0, então existe um nó r, chamado raiz de T,
onde:
• r possui nós descendentes, em que cada nó é uma
subárvore.
• cada subárvore é, por sua vez, uma árvore que possui
uma raiz.
Árvores Binárias
• É uma árvore T que está vazia ou está
particionada em três subconjuntos disjuntos:
– Raiz: r
– Subárvore à esquerda: lt
– Subárvore à direita: rt
Árvores Binárias
• É uma árvore T que está vazia ou está
particionada em três subconjuntos disjuntos:
– Raiz: r
– Subárvore à esquerda: lt
– Subárvore à direita: rt
Árvores Binárias
• É uma árvore T que está vazia ou está
particionada em três subconjuntos disjuntos:
– Raiz: r
– Subárvore à esquerda: lt
– Subárvore à direita: rt
Árvores Binárias
• É uma árvore T que está vazia ou está
particionada em três subconjuntos disjuntos:
– Raiz: r
– Subárvore à esquerda: lt
– Subárvore à direita: rt
Árvores Binárias
• É uma árvore T que está vazia ou está
particionada em três subconjuntos disjuntos:
– Raiz: r
– Subárvore à esquerda: lt
– Subárvore à direita: rt
Árvores Binárias
• É uma árvore T que está vazia ou está
particionada em três subconjuntos disjuntos:
– Raiz: r
– Subárvore à esquerda: lt
– Subárvore à direita: rt
Árvores Binárias
• É uma árvore T que está vazia ou está
particionada em três subconjuntos disjuntos:
– Raiz: r
– Subárvore à esquerda: lt
– Subárvore à direita: rt
Definições
• Raiz: r
– Primeiro elemento de um (sub)conjunto.
• Subárvore à esquerda: lt
– Descentes de r à esquerda
• Subárvore à direita: rt
– Descentes de r à direita
• Grau de um nó: g(v)
– Número de filhos de um nó
• Grau de uma árvore: g(T)
– Valor máximo entre os graus de seus nós.
• Nó folha: vl
– Nó que não possui descendentes, ou seja, possui grau = 0
• Nó interno: vi
– Nó que possui grau > 0, ou seja, que não é folha ...
Definições
• Nível de um nó v: d(v)
– número de ligações de v até a raiz r de T (a raiz
tem nível 0)
– denota a profundidade de v
• Altura de um nó v: h(v)
– O maior caminho de v até um de seus nós folha
descendentes.
• Altura de uma árvore: h(T)
– O maior nível entre a raiz r e um de seus nós folha.
Definições
• Raiz da Árvore: A d0
• Folhas: D, G, H, I d1
• Níveis: d0, ..., d3
• Grau da árv.: 2
d2
• O pai de E é B
• Filho Esquerdo de B é D
• Filho Direito de A é C d3
• O irmão de D é E
• Sub-árvores vazias: 10
• Sub-árvores não-vazias: 8
• Altura da árvore: nível máximo (3)
• Descendentes B: D, E, G
• Ascendentes de H: F, C, A
Árvore Estritamente Binária
• Todo nó que não é folha deve possuir
subárvores à esquerda e à direita não-vazias
Árvore Binária completa
• Deve ser uma árvore estritamente binária
• Todos os nós folha devem estar num nível d
ou d-1
Árvore Binária cheia
• Deve ser uma árvore estritamente binária
• Todos os nós folha devem estar num
mesmo nível d
Operações sobre Árvores Binárias
• Principais operações:
– percurso
• Profundidade
• Largura
– inserção
– busca
– predecessor
– sucessor
– remoção
– altura
– nível
Representação de uma árvore binária

struct bin_node{
int key;
struct bin_node *left;
struct bin_node *right;
};

typedef struct bin_node bin_node;


Percurso em Profundidade
• Pre-ordem:
1. Visitar a raiz
2. Percorrer a subarvore esquerda em pre-ordem
3. Percorrer a subarvore direita em pre-ordem
• Pós-ordem:
1. Percorrer a subarvore esquerda em pós-ordem
2. Percorrer a subarvore direita em pós-ordem
3. Visitar a raiz
• Em-ordem:
1. Percorrer a subarvore esquerda em em-ordem
2. Visitar a raiz
3. Percorrer a subarvore direita em em-ordem
Percurso em Profundidade
• Pre-ordem:
1. Visitar a raiz
2. Percorrer a subarvore esquerda em pre-ordem
3. Percorrer a subarvore direita em pre-ordem

Percurso em Pré-ordem:
ABDEGCFH
void preorder(node *r){
if (!r) return;
visit(r);
preorder(r->left);
preorder(r->right);
}
Percurso em Profundidade
• Pós-ordem:
1. Percorrer a subarvore esquerda em pós-ordem
2. Percorrer a subarvore direita em pós-ordem
3. Visitar a raiz
Percurso em Pós-ordem:
DGEBHFCA

void postorder(node *r){


if (!r) return;
postorder(r->left);
postorder(r->right);
visit(r);
}
Percurso em Profundidade
• Em-ordem:
1. Percorrer a subárvore esquerda em em-ordem
2. Visitar a raiz
3. Percorrer a subárvore direita em em-ordem

Percurso em Em-ordem:
DBGEAFHC
void inorder(node *r){
if (!r) return;
inorder(r->left);
visit(r);
inorder(r->right);
}
Árvore binária de busca
• Como o próprio nome sugere, é uma árvore T
do tipo binária (não necessariamente
estritamente binária).
• No entanto, possui as seguintes restrições:
– dada uma raiz r,
• se vl é um nó à esquerda de r, então key[vl] <= key[r]
• Se vr é um nó à direita de r, então key[vr] > key[r]
Árvore binária de busca
Operação de Inserção em uma Árvore
Binária de Busca
• Considere o vetor abaixo:
15 6 7 18 3 13 2 9 4 17 20

INSERT (T, K)
Complexidade O(log n) If T == NIL Then
T = NEW_NODE(K)
NEW_NODE
Else If (K <= T.k) Then
T.left = INSERT (T.left, K)
Else
T.right = INSERT (T.right, k)
RETURN T
15 6 7 18 3 13 2 9 4 17 20

15

6 18

3 7 17 20

INSERT (T, K)
If T == NIL Then
2 4 13 T = NEW_NODE(K)
NEW_NODE
Else If (K <= T.k) Then
T.left = INSERT (T.left, K)
Else
T.right = INSERT (T.right, k)
9 RETURN T
15 6 7 18 3 13 2 9 4 17 20

15

INSERT (T, K)
If T == NIL Then
T = NEW_NODE(K)
NEW_NODE
Else If (K <= T.k) Then
T.left = INSERT (T.left, K)
Else
T.right = INSERT (T.right, k)
RETURN T
15 6 7 18 3 13 2 9 4 17 20

15

INSERT (T, K)
If T == NIL Then
T = NEW_NODE(K)
NEW_NODE
Else If (K <= T.k) Then
T.left = INSERT (T.left, K)
Else
T.right = INSERT (T.right, k)
RETURN T
15 6 7 18 3 13 2 9 4 17 20

15

INSERT (T, K)
If T == NIL Then
T = NEW_NODE(K)
NEW_NODE
Else If (K <= T.k) Then
T.left = INSERT (T.left, K)
Else
T.right = INSERT (T.right, k)
RETURN T
15 6 7 18 3 13 2 9 4 17 20

15

6 18

INSERT (T, K)
If T == NIL Then
T = NEW_NODE(K)
NEW_NODE
Else If (K <= T.k) Then
T.left = INSERT (T.left, K)
Else
T.right = INSERT (T.right, k)
RETURN T
15 6 7 18 3 13 2 9 4 17 20

15

6 18

3 7

INSERT (T, K)
If T == NIL Then
T = NEW_NODE(K)
NEW_NODE
Else If (K <= T.k) Then
T.left = INSERT (T.left, K)
Else
T.right = INSERT (T.right, k)
RETURN T
15 6 7 18 3 13 2 9 4 17 20

15

6 18

3 7

INSERT (T, K)
If T == NIL Then
13 T = NEW_NODE(K)
NEW_NODE
Else If (K <= T.k) Then
T.left = INSERT (T.left, K)
Else
T.right = INSERT (T.right, k)
RETURN T
15 6 7 18 3 13 2 9 4 17 20

15

6 18

3 7

INSERT (T, K)
If T == NIL Then
2 13 T = NEW_NODE(K)
NEW_NODE
Else If (K <= T.k) Then
T.left = INSERT (T.left, K)
Else
T.right = INSERT (T.right, k)
RETURN T
15 6 7 18 3 13 2 9 4 17 20

15

6 18

3 7

INSERT (T, K)
If T == NIL Then
2 13 T = NEW_NODE(K)
NEW_NODE
Else If (K <= T.k) Then
T.left = INSERT (T.left, K)
Else
T.right = INSERT (T.right, k)
9 RETURN T
15 6 7 18 3 13 2 9 4 17 20

15

6 18

3 7

INSERT (T, K)
If T == NIL Then
2 4 13 T = NEW_NODE(K)
NEW_NODE
Else If (K <= T.k) Then
T.left = INSERT (T.left, K)
Else
T.right = INSERT (T.right, k)
9 RETURN T
15 6 7 18 3 13 2 9 4 17 20

15

6 18

3 7 17

INSERT (T, K)
If T == NIL Then
2 4 13 T = NEW_NODE(K)
NEW_NODE
Else If (K <= T.k) Then
T.left = INSERT (T.left, K)
Else
T.right = INSERT (T.right, k)
9 RETURN T
15 6 7 18 3 13 2 9 4 17 20

15

6 18

3 7 17 20

INSERT (T, K)
If T == NIL Then
2 4 13 T = NEW_NODE(K)
NEW_NODE
Else If (K <= T.k) Then
T.left = INSERT (T.left, K)
Else
T.right = INSERT (T.right, k)
9 RETURN T
Busca
• Dada uma árvore T e uma chave k,
implemente uma função de busca que:
– retorne o nó TRUE, se k existir em T
– Ou retorne FALSE, caso contrário

SEARCH(T,
SEARCH K)
If T == NIL Then
RETURN false
O(log n) Else If (K < T.k) Then
RETURN SEARCH (T.left, K)
Else If (K > T.k)
RETURN SEARCH (T.right, k)
RETURN true
Remoção
15

6 18

3 7 17 20

2 4 13

9
Remoção
• Existem 3 situações
– Remoção de um nó folha
– Remoção de um nó raiz com grau 1
– Remoção de um nó raiz com grau 2
15

6 18

3 7 17 20

2 4 13

9
Remoção
• Existem 3 situações
– Remoção de um nó folha
– Remoção de um nó raiz com grau 1
– Remoção de um nó raiz com grau 2
15

6 18

3 7 17 20

2 4 13

9
Remoção
• Existem 3 situações
– Remoção de um nó folha
– Remoção de um nó raiz com grau 1
– Remoção de um nó raiz com grau 2
15

6 18

3 7 17 20

2 4 13
Remoção
• Existem 3 situações
– Remoção de um nó folha
– Remoção de um nó raiz com grau 1
– Remoção de um nó raiz com grau 2
15

6 18

3 7 17 20

2 4 13
Remoção
• Existem 3 situações
– Remoção de um nó folha
– Remoção de um nó raiz com grau 1
– Remoção de um nó raiz com grau 2
15

6 18

3 7 17 20

2 4 13
Remoção
• Existem 3 situações
– Remoção de um nó folha
– Remoção de um nó raiz com grau 1
– Remoção de um nó raiz com grau 2
15

6 18

3 13 17 20

2 4
Remoção
• Existem 3 situações
– Remoção de um nó folha
– Remoção de um nó raiz com grau 1
– Remoção de um nó raiz com grau 2
15

6 18

3 13 17 20

2 4
Remoção
• Existem 3 situações
– Remoção de um nó folha
– Remoção de um nó raiz com grau 1
– Remoção de um nó raiz com grau 2
15

1: Encontre um r’ tal que r’ seja o


6 18 nó mais à direita a subarvore à
esquerda de r

3 13 17 20

2 4
Remoção
• Existem 3 situações
– Remoção de um nó folha
– Remoção de um nó raiz com grau 1
– Remoção de um nó raiz com grau 2
15

r
1: Encontre um r’ tal que r’ seja o
6 18 nó mais à direita a subarvore à
esquerda de r

3 13 17 20

2 4
Remoção
• Existem 3 situações
– Remoção de um nó folha
– Remoção de um nó raiz com grau 1
– Remoção de um nó raiz com grau 2
15

r
1: Encontre um r’ tal que r’ seja o
6 18 nó mais à direita a subarvore à
esquerda de r

3 13 17 20

2 4
Remoção
• Existem 3 situações
– Remoção de um nó folha
– Remoção de um nó raiz com grau 1
– Remoção de um nó raiz com grau 2
15

r
1: Encontre um r’ tal que r’ seja o
6 18 nó mais à direita a subarvore à
esquerda de r

3 13 17 20

2 4
Remoção
• Existem 3 situações
– Remoção de um nó folha
– Remoção de um nó raiz com grau 1
– Remoção de um nó raiz com grau 2
15

r
1: Encontre um r’ tal que r’ seja o
6 18 nó mais à direita a subarvore à
esquerda de r
2: troque a chave r.key com r’.key
3 13 17 20

2 4
Remoção
• Existem 3 situações
– Remoção de um nó folha
– Remoção de um nó raiz com grau 1
– Remoção de um nó raiz com grau 2
15

r
1: Encontre um r’ tal que r’ seja o
4 18 nó mais à direita a subarvore à
esquerda de r
2: troque a chave r.key com r’.key
3 13 17 20

2 6
Remoção
• Existem 3 situações
– Remoção de um nó folha
– Remoção de um nó raiz com grau 1
– Remoção de um nó raiz com grau 2
15

r
1: Encontre um r’ tal que r’ seja o
4 18 nó mais à direita a subarvore à
esquerda de r
2: troque a chave r.key com r’.key
3 13 17 20 3: remova recursivamente key a
partir de r.left
2 6
Remoção
• Existem 3 situações
– Remoção de um nó folha
– Remoção de um nó raiz com grau 1
– Remoção de um nó raiz com grau 2
15

r
1: Encontre um r’ tal que r’ seja o
4 18 nó mais à direita a subarvore à
esquerda de r
2: troque a chave r.key com r’.key
3 13 17 20 3: remova recursivamente key a
partir de r.left
2 6
Remoção
• Existem 3 situações
– Remoção de um nó folha
– Remoção de um nó raiz com grau 1
– Remoção de um nó raiz com grau 2
15

1: Encontre um r’ tal que r’ seja o


4 18 nó mais à direita a subarvore à
esquerda de r
2: troque a chave r.key com r’.key
3 13 17 20 3: remova recursivamente key a
partir de r.left
2

Você também pode gostar