Estrutura de Dados
Tema 6: Árvores
binárias.
Segundo Knuth (1973), uma árvore pode ser formalmente definida como sendo um conjunto finito T de um ou mais nós, onde:
a) existe um nó especialmente designado para ser a raiz de T; e
b) os demais nós são parti- cionados dentro de m≥0 conjuntos disjuntos T1,T2,
..., Tm e cada um destes
conjuntos torna-se uma árvore, chamada sub-árvores da raiz.
O que é uma árvore
Características de uma árvore
raiz:- o nó inicial da árvore;
Grau: o número de filhos que um nó possui;
Nível (ou profundidade): a distância de um nó até a raiz;
Altura: o maior nível encontrado na árvore (altura de uma árvore com n nós pode variar de lg(n) até n-1;
6
9 14
25
folha Este nó está no nível 2 e possui grau 0. Este nó está no nível
1 e possui grau 1.
Este nó está no nível 0 e possui grau 2. raiz
folha
Este nó está no nível 1 e possui grau 0.
Altura da árvore é 2
O que não é uma árvore
AB C
D G
D C
A B
O que é uma árvore binária
Um conjunto de finito de elementos que pode estar vazio ou particionado em 3 subconjuntos disjuntos.
A
B C
Árvore binária
• Em uma árvore binária os nós podem assumir grau 0, 1 ou 2;
• Em uma árvore binária completa, todos os nós possuem grau igual a 2;
• O número máximo de elementos em uma árvore de altura n é 2n.
Árvore binária de busca
Uma árvore binária de busca possui elementos menores que a raiz armazenados na sub-árvore da esquerda e elementos maiores que a raiz na sub-árvores da direita.
25
38 12
19
Árvore binária como um TDA
Características:• Conjunto de elementos;
Árvore binária de busca como um TDA
Operações:
• Inserir novo elemento • Buscar um elemento • Mostrar todos os
elementos
• Remover um elemento • Contar elementos • Calcular nível de um elemento
Inserção de elementos em uma
árvore binária de busca
• O primeiro elemento inserido assumirá o papel
de raiz da árvore;
• Todo novo elemento entrará na árvore como
uma folha;
• Se o elemento for menor
ou igual à raiz será in- serido no ramo da esquer- da. Caso contrário, no ramo da direita (para árvores decrescentes inverte-se a a regra).
Análise gráfica de inserções em uma
árvore binária
Continuando
Tema 6: Árvores binárias.
Remoção de elementos em uma árvore
binária de busca
Podem ocorrer as seguintes situações:
1. Elemento a ser removida é uma folha (sem
filhos à esquerda e à direita);
2. Elemento a ser removido possui apenas um filho (à direita ou à esquerda); 3. Elemento a ser removido
possui dois filhos.
Remoção na situação 1
Remover os elementos 19 e 3825
38 12
19
25
Remoção na situação 2 – filho à
esquerda
Remover os elementos 12 e 65
29
65 12
34 58 5 49
29
5
34 58 49
Remoção na situação 2 – filho à
direita
Remover os elementos 19 e 87
58
87 19
24 41 94 37
58
94
24 41 37
Remoção na situação 3 – filhos à
esquerda e à direita
Remover o elemento 23 e 67- estratégia 1
58
60
28 54 45 4
2 15 94
58
67 23
28 54 45 4
2 15
Remoção na situação 3 – filhos à
esquerda e à direita
Remover o elemento 23 e 67 -estratégia 2
58
94
28 54 45
4
2 15
60 58
67 23
28 54 45 4
2 15
60 94
Percurso em uma árvore binária
1. Pré-ordem: raiz, árvore esquerda, sub-árvore direita
2. Em ordem: árvore esquerda, raiz, sub-árvore direita
3. Pós-ordem: sub-árvore esquerda, sub-árvore direita, raiz
Exemplo de percurso pré-ordem
Pré-ordem: H, F, C, D, Q, L, J, N, UH
Q F
J C
D
L U
Exemplos de percurso em ordem
Em ordem: C, D, F, H, J, L, N, Q, U
H
Q F
J C
D
L U
N
Exemplos de percurso pós-ordem
Pós-ordem: D, C, F, J, N, L, U, Q, HH
Q F
J C
D
L U
N
Implementar em C funções que utilizem uma árvore binária de busca para:
• inserir elementos • remover elementos
• percorrer a árvore:pré-ordem • percorrer a árvore: em
ordem
• percorrer a árvore: pós-ordem
#include <stdio.h> #include <stdlib.h>
struct arvoreBinaria { int elem;
arvoreBinaria *dir, *esq; };
…
int main() {
arvoreBinaria *raiz, *p; int x; char op; raiz = NULL;
do { fflush(stdin);
printf("\n1- Inserir\n2- Excluir \n3-preOrdem \n4- emOrdem\n5- posOrdem \n6- Sair "); scanf("%c", &op);
switch (op) { case '1':
case '2':
if (raiz != NULL) {
printf("\nDigite um valor "); scanf("%d", &x);
raiz=remove(raiz,x); }
else printf("\nArvore vazia.\n");
break;
case ‘ 3': preOrdem(raiz); break;
case '4':
emOrdem(raiz); break;
case ‘5':
posOrdem(raiz); } // fim switch }while (op!=‘ 6'); }
arvoreBinaria *insere(arvoreBinaria *a, int el) {
if (a == NULL) {
a = new (arvoreBinaria); a->elem = el;
else { if (el <= a->elem)
a->esq=insere(a->esq, el); else a->dir=insere(a->dir, el); } return a;
}
arvoreBinaria *remove(arvoreBinaria *a, int el) {
arvoreBinaria *p, *p2;
if (a->elem == el) {
if (a->esq == a->dir) { // remoção de folha
delete(a); return NULL; }
else if (a->esq == NULL) { //filho a direita p=a->dir;
delete(a); return p; }
else if (a->dir == NULL) { //filho a esq
p=a->esq; delete(a); return p; }
else { //tem 2 filhos p2= a->dir; p= a->dir;
while (p->esq) p=p->esq; p->esq = a->esq; delete(a); return p2; }
if (a->elem < el) {
if (a->dir!=NULL) a->dir = remove(a->dir, el); else printf(“Elemento nao encontrado."); }
else { if (a->esq!=NULL)
a->esq = remove(a->esq, el); else printf(“Elemento
não encontrado"); }
return a; }
void preOrdem(arvoreBinaria *a) { if (a != NULL)
{ printf("\n%d ", a->elem); preOrdem(a->esq); preOrdem(a->dir); }
}
void emOrdem(arvoreBinaria *a) { if (a != NULL)
{ emOrdem(a->esq); printf("\n%d ", a->elem); emOrdem(a->dir); }
void posOrdem(arvoreBinaria *a) { if (a != NULL)
{ posOrdem(a->esq); posOrdem(a->dir);
printf("\n%d ", a->elem); }
}
Finalizando
Tema 6: Árvores binárias.Árvore AVL
Quando os ramos (sub-árvores) ficarem com alturas muito diferentes, as árvores passam a ficar semelhantes às estruturas lineares (listas,
filas e pilhas), nas quais o processo de busca é menos eficiente.
Árvore AVL (
Adelson- Velsky e Landis)
Uma árvore AVL é uma árvore binária onde as alturas das duas sub-árvores de qualquer nó nunca ultrapassa 1.
O balanceamento de um nó é definido como a altura de sua sub-árvore
esquerda menos a altura de sua sub-árvore direita.
| alt_esq – alt_dir | ≤ 1
Como garantir o balanceamento?
Após uma inserção ou remoção, deve-se promover ajustes na árvores, de tal forma que: a) A árvore continue sendo uma árvore bináriade busca (a ordenação dos elementos seja mantida);
b) O módulo da diferença entre as alturas das sub-árvores esquerda e direita de qualquer nó seja inferior a 1.
Como garantir o balanceamento?
Os ajustes são chamados Rotações (à direita ou à esquerda).Seja N o nó desbalanceado, poderá ser preciso: a) Rotação Simples – rotaciona-se apenas N b) Rotação Dupla – primeiro
Rotação simples para direita
A inserção de A provoca desbalanceamento em F.
H
Q F
J C
A
L U
N
H
Q C
J
A F L U
N
Rotação simples para direita
A inserção de 15 provoca desbalanceamento em 30.
30
90 20
10
15 28
20
30 10
15 28 90
Rotação simples para esquerda
A inserção de G provoca desbalanceamento em C.
J
Q F
G L U
N C
J
Q C
G
F L U
Rotação simples para esquerda
A inserção de R provoca desbalanceamento em J.
Q
U J
L R
C J
Q C
L U
R
Rotação dupla (direita - esquerda)
A inserção de 19 provoca desbalanceamento em 32. 37 59 14 8 19 26 1ª 2ª 37 59 26 14 19 2ª 8 26 37 14
8 19 59
Rotação dupla (esquerda - direita)
A inserção de 40 provoca desbalanceamento em 35.
35
21 68