Buscar

Árvores AVL

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 3, do total de 97 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 6, do total de 97 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 9, do total de 97 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Prévia do material em texto

• O processo de busca na ABB é mais rápido do que
em listas encadeadas.
• As ABB’s diminuem consideravelmente a
quantidade de comparações necessárias para
encontrar uma informação.
• No entanto, dependendo da ordem em que os nós
forem inseridos/removidos da ABB, ela pode ficar
muito desbalanceada.
Árvore Binária de Busca - ABB
 Se os nós forem inseridos na ordem crescente ou
decrescente, a ABB se tornará desbalanceada (árvore
degenerada):
Árvore Binária de Busca - ABB
Árvore Binária de Busca - ABB
 Todas armazenam os mesmos dados ordenados.
 Qual delas é a melhor? Qual é a pior?
 Quantas comparações são necessárias para se encontrar o 
elemento R na árvore (a)? E na árvore (c)?
 A quantidade de comparações que precisamos fazer
para encontrar um nó na árvore depende
diretamente da altura da árvore.
Árvores
Procurar pela chave 34 na ABB:
Exemplo
33
40
17 45
2810 53
439 35
34
Quantas comparações?
 Neste caso teremos que fazer cinco comparações
para encontrar a chave 34, proporcional a altura da
árvore!
 Quanto mais balanceada é a árvore, menor a sua
altura.
 Uma árvore está balanceada se a altura de suas
subárvores se diferem em no máximo uma unidade.
Árvores
 Nesta árvore todas as subárvores estão balanceadas, com
exceção da subárvore com raiz em 45.
 A subárvore 45 está desbalanceada, pois a altura de sua
subárvore esquerda é 3 e a altura de sua subárvore direita é 1,
com uma diferença de duas unidades.
33
40
17 45
2810 53
439 35
34
Árvore Desbalanceada:
 Se tivéssemos 1.048.575 nós, poderíamos armazená-los em
uma árvore binária perfeitamente balanceada com 20 níveis.
 Em outras palavras, poderíamos localizar um elemento
qualquer dentro dessa árvore com no máximo 20
comparações.
Vantagem da Árvore Balanceada
Altura Nós no último nível Nós em todos os níveis
1 20 = 1 21 - 1 = 1
2 21 = 2 22 - 1 = 3
3 22 = 4 23 - 1 = 7
20 219 = 524.288 220 - 1 = 1.048.575
h 2h - 1 2h - 1 = n
 Dizemos que uma árvore está balanceada quando, para
cada nó da mesma, a diferença entre as alturas de suas
duas subárvores é igual a -1, 0 ou 1.
 A esta diferença de altura damos o nome de fator de
balanceamento.
Árvores Balanceadas
 As figuras abaixo mostram as árvores anteriores com a
indicação em cada nó da diferença de altura entre suas
subárvores direita e esquerda.
Árvores Balanceadas
K
M
B P
D R
0
000
0
1
B
D
K
P
M R
0 0
0
0
1
3
R
B
D
K
M
P
1
0
2
3
4
5
 Árvore AVL (ou árvore balanceada pela altura) é
uma árvore binária de busca auto-balanceada.
 As árvores AVL têm o objetivo de manter a árvore
sempre balanceada, diminuindo assim a quantidade de
comparações feitas pelas operações de busca, inserção e
remoção.
Árvores AVL
 A ideia é a seguinte:
 Após cada operação de inserção/remoção na árvore,
verificar se algum nó se tornou desbalanceado.
 Em caso positivo, algumas operações adicionais devem
ser realizadas para tornar a árvore novamente
balanceada.
 A sigla AVL se refere aos criadores deste método, os
matemáticos russos Adelson-Velskii e Landis.
Árvores AVL
Operação de inserção:
 Calcular o FB dos nós que estão entre o nó que
acabou de ser inserido e a raiz da árvore, procurando
por um nó com FB=2 ou FB= -2, o que indica que a
subárvore com raiz naquele nó está desbalanceada.
 O FB de um nó X é a diferença entre a altura (h) de
sua subárvore direita e a altura da subárvore
esquerda.
Fator de Balanceamento
FB(X) = h(subárvore direita de X) – h(subárvore esquerda de X).
 Quando a árvore está desbalanceada deve-se efetuar
“rotações” em nós desbalanceados.
 Rotação ocorre quando o peso se torna maior em
um dos lados da árvore.
 Exemplo: inserção de X na direita.
Rotações
1
2
4
3 5
X
Exemplo: inserção de X na direita.
Rotações
1
2
4
3 5
X
FB(4) = 2 – 1 = 1  balanceado
FB(X) = h(subárvore direita de X) – h(subárvore esquerda de X).
Exemplo: inserção de X na direita.
Rotações
1
2
4
3 5
X
FB(2) = 3 – 1 = 2  desbalanceado
FB(4) = 2 – 1 = 1  balanceado
Rotações são feitas da seguinte forma:
FB > 1 => rotações para a esquerda do nó;
FB < -1 => rotações para a direita do nó.
Rotações
 FB(2) = 3 – 1 = 2  desbalanceada para a direita.
 Efetua-se rotação para esquerda:
Rotação para Esquerda
1
2
4
3 5
X
Efetua-se rotação para esquerda, obtendo-se a
árvore balanceada:
Rotação para Esquerda
2
4
1 3
5
X
FB(2) = 1 – 1 = 0
FB(4) = 2 – 2 = 0  balanceado.
1
2
4
3 5
X
Inserção a direita:
EXEMPLO 1
FB=2
35
45
20 50
2815 60
58 65
69
FB=1
FB(69) = 0  Toda folha tem FB zero.
FB(65) = 1 – 0 = 1
FB(60) = 2 – 1 = 1
FB(50) = 3 – 1 = 2 => desbalanceado para a direita.
Inserção de 69
 Como o nó desbalanceado (50) tem FB com o mesmo sinal
do FB do filho (60), então basta uma operação de rotação do
pai para tornar a árvore balanceada novamente.
Rotação
FB=2
35
45
20 50
2815 60
58 65
69
FB=1
No exemplo, como FB(50) > 1, devemos rotacionar o nó 50 para
a esquerda.
Rotação para Esquerda
FB=2
35
45
20 50
2815 60
58 65
69
FB=1
Árvore resultante da rotação de 50 à esquerda:
Árvore Balanceada
35
50
20 60
2815 65
5845
69
FB=2
35
45
20 50
2815 60
58 65
69
FB=1
Inserção a esquerda:
EXEMPLO 2
50
58
40 63
4830 70
20 35
15 Inserção de 15
Inserção a esquerda:
EXEMPLO 2
50
58
40 63
4830 70
20 35
15FB(20) = 0 – 1 = -1
FB(30) = 1 – 2 = -1
FB(40) = 1 – 3 = -2 => desbalanceado para a esquerda.
Inserção de 15
FB(40) < -1 => rotação à direita.
Rotação
50
58
40 63
4830 70
20 35
15
FB(40) < -1 => rotação à direita.
Rotação
50
58
40 63
4830 70
20 35
15
50
5840
6330
20 70
4835
15
 O caso mais complexo é quando o FB do nó
desbalanceado tem sinal contrário ao do nó filho.
 Neste caso são necessárias duas rotações:
 Primeiramente a rotação do filho para a direção
correspondente ao sinal do seu FB;
 Depois a rotação do pai (desbalanceado) para a
direção contrária.
Duas Rotações
Considere a seguinte árvore, onde o nó 78 foi inserido:
Exemplo 3
FB=-1
FB=2
50
6028
7520
15 90
9385
78
FB(85) = 0 – 1 = -1
FB(90) = 1 – 2 = -1
FB(75) = 3 – 1 = 2 => desbalanceado
Duas Rotações
2º
1º
FB=-1
FB=2
50
6028
7520
15 90
9385
78
FB(75) > 0 e FB(90) < 0 => duas rotações:
• Rotação à direita de 90 e
• Rotação à esquerda de 75.
Primeira Rotação
1º
FB=-1
FB=2
50
6028
7520
15 90
9385
78
Árvore resultante da rotação a direita de 90:
Primeira Rotação
FB=2
50
6028
7520
15 85
9078
93
Segunda Rotação
FB=2
50
6028
7520
15 85
9078
93
Segunda Rotação
FB=2
50
6028
7520
15 85
9078
93
FB=0
50
7528
8520
15 90
937860
Considere a árvore abaixo, onde o nó 25 foi inserido:
Exemplo 4
FB=1
FB= -2
50
5532
6030
15 70
25
2010
FB(20) = 1 – 0 = 1
FB(15) = 2 – 1 = 1
FB(30) = 1 – 3 = -2 => desbalanceado para a esquerda.
FB(30) < -1 e FB(15) > 0 => duas rotações: rotação à esquerda 
de 15 e rotação à direita de 30.
Rotação a Esquerda
FB=1
FB= -2
50
5532
6030
15 70
25
2010
Veja abaixo após a rotação à esquerda de 15.
Rotação a Esquerda
FB=-2
50
5532
6030
20 70
25
1015
FB=1
FB= -2
50
5532
6030
15 70
25
2010
Árvore resultante da rotação à direita de 30:
Rotação a Direita
50
5530
6020
15 70
2510 32
 Podem ocorrer quatro tipos de rotações, identificados
pelo FB(pai) e FB(filho).
 FB(pai) pode assumir os valores 2 ou -2, enquanto que o
FB(filho) pode assumir os valores 1 ou -1.
 Casos possíveis:
 FB(pai) = 2 e FB(filho) = 1
 FB(pai) = -2 e FB(filho) = -1
 FB(pai) = 2 e FB(filho) = -1 (sinal contrário)
 FB(pai) = -2 e FB(filho) = 1 (sinal contrário)
RESUMO DAS ROTAÇÕES
FB(pai) = 2 e FB(filho) = 1
RESUMO: Caso 1
1
pai
filho
3 5
X
FB(pai) = 2 e FB(filho) = 1
Balanceamento = rotação do pai para esquerda.
RESUMO: Caso 1
1
pai
filho
3 5
X
pai
filho
1 3
5
X
FB(pai) = -2 e FB(filho) = -1
Resumo: Caso 2
6
pai
filho
42
X
FB(pai) = -2 e FB(filho) = -1
Balanceamento = rotação do pai para direita.
Resumo: Caso 2
6
pai
filho
42
X
pai
filho
4 6
X
2
FB(pai) = 2 e FB(filho) = -1 (sinal contrário)
Resumo: Caso 3
pai
filho
3 6
X
1
FB(pai) = 2 e FB(filho) = -1 (sinal contrário)
Balanceamento:
 rotação do filho p/ direita;
 rotação do pai p/ esquerda.
Resumo: Caso 3
pai
filho
3 6
X
1
pai
filho
3
6
X
1
FB(pai) = 2 e FB(filho) = -1 (sinal contrário)
Balanceamento:
 rotação do filho p/ direita;
 rotação do pai p/ esquerda.
Resumo: Caso 3
pai
filho
3 6
X
1
pai
filho
3
6
X
1
FB(pai) = 2 e FB(filho) = -1 (sinal contrário)
Balanceamento:
 rotação do filho p/ direita;
 rotação do pai p/ esquerda.
Resumo: Caso 3
pai
filho
3
6
X
1
pai filho
3
6X1
pai
filho
3 6
X
1
FB(pai) = -2 e FB(filho) = 1 (sinal contrário)
Resumo: Caso 4
6
pai
filho
31
X
FB(pai) = -2 e FB(filho) = 1 (sinal contrário)
Balanceamento:
 rotação do filho p/ esquerda;
 rotação do pai p/ direita.
Resumo: Caso 4
6
pai
filho
3
1
X
6
pai
filho
31
X
FB(pai) = -2 e FB(filho) = 1 (sinal contrário)
Balanceamento:
 rotação do filho p/ esquerda;
 rotação do pai p/ direita.
Resumo: Caso 4
6
pai
filho
3
1
X
6
pai
filho
31
X
FB(pai) = -2 e FB(filho) = 1 (sinal contrário)
Balanceamento:
 rotação do filho p/ esquerda;
 rotação do pai p/ direita.
Resumo: Caso 4
6
pai
filho
3
1
X
6
paifilho
3
1
X
6
pai
filho
31
X
 Vamos definir a estrutura do No da Árvore
AVL contendo:
 As referências à direita e à esquerda;
 Um campo que comporte a altura do nó;
 Um campo que comporte o FB do nó.
Definição da Estrutura
Definição da Estrutura
typedef struct estrutura{
TIPOCHAVE info;
int altura, fb;
struct estrutura* esq;
struct estrutura* dir;
} NO;
Definição da Estrutura
typedef int TIPOCHAVE;
typedef struct estrutura{
TIPOCHAVE info;
int altura, fb;
struct estrutura* esq;
struct estrutura* dir;
} NO;
typedef struct {
NO* raiz;
} ARVORE;
Inicialização
typedef int TIPOCHAVE;
typedef struct estrutura{
TIPOCHAVE info;
int altura, fb;
struct estrutura *esq;
struct estrutura *dir;
} NO;
typedef struct {
NO *raiz;
} ARVORE;
void inicializarArvore(ARVORE* a){
a->raiz = NULL;
}
Mostrar a Árvore
void mostrar(NO* no){
if (no){
printf("[");
mostrar(no->esq);
printf(“%d.a%d.fb%d", no->info, 
no->altura,
no->fb);
mostrar(no->dir);
printf("]");
}
}
Exemplo: [[100.a1.fb0]120.a2.fb0[150.a1.fb0]]
 Escreva uma função que calcule a altura e o FB do
nó corrente baseado nas informações de seus nós
filhos.
Calcular Altura e 
Fator de Balanciamento
NO* calculaAlturaFB(NO* no){
//obter a altura do nó a esquerda
//obter a altura do nó a direita
//calcular a altura deste nó
//calcular FB deste nó
NO* calculaAlturaFB(NO* no){
int altEsq, altDir;
//obter a altura do nó a esquerda
if (!no->esq) altEsq = 0;
else altEsq = no->esq->altura;
//obter a altura do nó a direita
Calcular Altura e 
Fator de Balanciamento
NO* calculaAlturaFB(NO* no){
int altEsq, altDir;
//obter a altura do nó a esquerda
if (!no->esq) altEsq = 0;
else altEsq = no->esq->altura;
//obter a altura do nó a direita
if (!no->dir) altDir = 0;
else altDir = no->dir->altura;
//calcular a altura deste nó
Calcular Altura e 
Fator de Balanciamento
NO* calculaAlturaFB(NO* no){
int altEsq, altDir;
//obter a altura do nó a esquerda
if (!no->esq) altEsq = 0;
else altEsq = no->esq->altura;
//obter a altura do nó a direita
if (!no->dir) altDir = 0;
else altDir = no->dir->altura;
//calcular a altura deste nó
if (altDir > altEsq) no->altura = altDir + 1;
else no->altura = altEsq + 1;
//calcular FB deste nó
Calcular Altura e 
Fator de Balanciamento
NO* calculaAlturaFB(NO* no){
int altEsq, altDir;
//obter a altura do nó a esquerda
if (!no->esq) altEsq = 0;
else altEsq = no->esq->altura;
//obter a altura do nó a direita
if (!no->dir) altDir = 0;
else altDir = no->dir->altura;
//calcular a altura deste nó
if (altDir > altEsq) no->altura = altDir + 1;
else no->altura = altEsq + 1;
//calcular FB deste nó
no->fb = altDir - altEsq;
return no;
}
Calcular Altura e 
Fator de Balanciamento
Escreva uma função que faça a rotação à direita do nó pai.
Rotação a Direita
6
5
3
42
X
pai
5
3
4 6
X
2
filho
NO* rotacaoDir(NO* no){ 
//Realiza a rotação para a DIREITA.
...
}
6
5
3
42
X
pai
filho
NO* rotacaoDir(NO* no){ 
NO *pai = no;
NO *filho = no->esq;
pai->esq = filho->dir;
filho->dir = pai;
no = filho;
no->dir = calculaAlturaFB(no->dir);
no = calculaAlturaFB(no);
return no;
}
5
3
4
X
2
6
Rotação a Direita
 Escreva uma função que faça a rotação à esquerda
do nó pai.
1
2
4
3 5
X
pai
filho
2
4
1 3
5
X
NO* rotacaoEsq(NO* no){ 
//Realiza a rotação para a ESQUERDA.
...
}
Rotação a Esquerda
1
2
4
3 5
X
pai
filho
2
4
1 3
5
X
NO* rotacaoEsq(NO* no){
NO *pai = no;
NO *filho = no->dir;
pai->dir = filho->esq;
filho->esq = pai;
no = filho;
no->esq = calculaAlturaFB(no->esq);
no = calculaAlturaFB(no);
return no;
}
Rotação a Esquerda
 Escreva uma função que recebe um nó
desbalanceado e faz as rotações necessárias para
balanceá-lo.
Balancear
NO* balancear(NO* no){
// Realiza os 4 casos de balanceamento.
...
}
Casos Gerais p/ Balanceamento
FB(pai) = 2 e FB(filho) = 1
rotação do pai para esquerda.
FB(pai) = -2 e FB(filho) = -1
rotação do pai para direita.
FB(pai) = 2 e FB(filho) = -1 (sinal contrário)
rotação do filho p/ direita;
rotação do pai p/ esquerda.
FB(pai) = -2 e FB(filho) = 1 (sinal contrário)
rotação do filho p/ esquerda;
rotação do pai p/ direita.
NO* balancear(NO* no){
if (no->fb == 2){
if (no->dir->fb == -1)
no->dir = rotacaoDir(no->dir);
no = rotacaoEsq(no);
}
else if (no->fb == -2){
if (no->esq->fb == 1)
no->esq = rotacaoEsq(no->esq);
no = rotacaoDir(no);
}
return no;
}
Balancear
 Criar uma função para inserir um novo elemento na
árvore AVL, mantendo o balanceamento.
NO* insereNO(NO* no, TIPOCHAVE valor){
//Insere um nó na árvore mantendo ordem. 
//Liga o novo nó na árvore na volta da recursão.
...
}
void insere(ARVORE* a, TIPOCHAVE ch){
a->raiz = insereNO(a->raiz, ch);
}
Inserir ElementoNO* insereNO(NO* no, TIPOCHAVE valor){
//Insere um nó na árvore mantendo ordem. 
//Liga o novo nó na árvore na volta da recursão.
//encontrou o lugar da inserção
if (!no){
no = (NO*) malloc(sizeof(NO));
no->info = valor;
no->esq = no->dir = NULL;
}
// decidir em que lado inserir
...
Inserir Elemento
NO* insereNO(NO* no, TIPOCHAVE valor){
//Insere um nó na árvore mantendo ordem. 
//Liga o novo nó na árvore na volta da recursão.
//encontrou o lugar da inserção
if (!no){
no = (NO*) malloc(sizeof(NO));
no->info = valor;
no->esq = no->dir = NULL;
}
// decidir em que lado inserir
else if (valor < no->info)
no->esq = insereNO(no->esq, valor);
else if (valor > no->info)
no->dir = insereNO(no->dir, valor);
else {//chave já existe
...
Inserir Elemento
NO* insereNO(NO* no, TIPOCHAVE valor){
if (!no){
no = (NO*) malloc(sizeof(NO));
no->info = valor;
no->esq = no->dir = NULL;
}
// decidir em que lado inserir
else if (valor < no->info)
no->esq = insereNO(no->esq, valor);
else if (valor > no->info)
no->dir = insereNO(no->dir, valor);
else {//chave já existe
printf("\nErro: a chave ja existe.");
return no;
}
no = calculaAlturaFB(no);
//verificar se esta balanceada
...
Inserir Elemento
NO* insereNO(NO* no, TIPOCHAVE valor){
if (!no){
no = (NO*) malloc(sizeof(NO));
no->info = valor;
no->esq = no->dir = NULL;
}
else if (valor < no->info)
no->esq = insereNO(no->esq, valor);
else if (valor > no->info)
no->dir = insereNO(no->dir, valor);
else {//chave já existe
printf("\nErro: a chave ja existe.");
return no; 
}
no = calculaAlturaFB(no);
//verifica se esta balanceada
if(no->fb == 2 || no->fb == -2){
no = balancear(no); 
}
return no;
}
Inserir Elemento
NO* insereNO(NO* no, TIPOCHAVE valor){
if (!no){
no = (NO*) malloc(sizeof(NO));
no->info = valor;
no->esq = no->dir = NULL;
}
else if (valor < no->info)
no->esq = insereNO(no->esq, valor);
else if (valor > no->info)
no->dir = insereNO(no->dir, valor);
else {//chave já existe
printf("\nErro: a chave ja existe.");
return no;
}
no = calculaAlturaFB(no);
//verifica se esta balanceada
if(no->fb == 2 || no->fb == -2){
no = balancear(no); }
return no;
}
void insere(ARVORE* a, TIPOCHAVE ch){
a->raiz = insereNO(a->raiz, ch);
}
Inserir Elemento
int main() {
ARVORE arv;
inicializarArvore(&arv);
insere(&arv, 100);
mostrar(arv.raiz);
}
Programa Principal
Inserir Elemento
int main() {
ARVORE arv;
inicializarArvore(&arv);
insere(&arv, 100);
mostrar(arv.raiz);
}
Programa Principal
[100.a1.fb0]
Inserir Elemento
int main() {
ARVORE arv;
inicializarArvore(&arv);
insere(&arv, 100);
insere(&arv, 120);
mostrar(arv.raiz);
}
Programa Principal
Inserir Elemento
int main() {
ARVORE arv;
inicializarArvore(&arv);
insere(&arv, 100);
insere(&arv, 120);
mostrar(arv.raiz);
}
Programa Principal
[[100.a2.fb1[120.a1.fb0]]
Inserir Elemento
int main() {
ARVORE arv;
inicializarArvore(&arv);
insere(&arv, 100);
insere(&arv, 120);
insere(&arv, 150);
printf("\n");
mostrar(arv.raiz);
}
Programa Principal
Inserir Elemento
int main() {
ARVORE arv;
inicializarArvore(&arv);
insere(&arv, 100);
insere(&arv, 120);
insere(&arv, 150);
printf("\n");
mostrar(arv.raiz);
}
Programa Principal
[[100.a1.fb0]120.a2.fb0[150.a1.fb0]]
Inserir Elemento
int main() {
ARVORE arv;
inicializarArvore(&arv);
insere(&arv, 100);
insere(&arv, 120);
insere(&arv, 150);
insere(&arv, 30);
printf("\n");
mostrar(arv.raiz);
}
Programa Principal
Inserir Elemento
int main() {
ARVORE arv;
inicializarArvore(&arv);
insere(&arv, 100);
insere(&arv, 120);
insere(&arv, 150);
insere(&arv, 30);
printf("\n");
mostrar(arv.raiz);
}
Programa Principal
[[[30.a1.fb0]100.a2.fb-1]120.a3.fb-1[150.a1.fb0]]
Inserir Elemento
int main() {
ARVORE arv;
inicializarArvore(&arv);
insere(&arv, 100);
insere(&arv, 120);
insere(&arv, 150);
insere(&arv, 30);
insere(&arv, 35);
printf("\n");
mostrar(arv.raiz);
}
Programa Principal
Inserir Elemento
int main() {
ARVORE arv;
inicializarArvore(&arv);
insere(&arv, 100);
insere(&arv, 120);
insere(&arv, 150);
insere(&arv, 30);
insere(&arv, 35);
printf("\n");
mostrar(arv.raiz);
}
Programa Principal
[[[30.a1.fb0]35.a2.fb0[100.a1.fb0]]120.a3.fb-1[150.a1.fb0]]
Inserir Elemento
 Remover 120:
Encontrar Antecessor
e Remover Elemento
120
100
150
30
35
no
noAnt
int main() {
ARVORE arv;
inicializarArvore(&arv);
insere(&arv, 100);
insere(&arv, 120);
insere(&arv, 150);
insere(&arv, 30);
insere(&arv, 35);
printf("\n");
mostrar(arv.raiz);
remover(120, &arv);
mostrar(arv.raiz);
}
 Remover 120:
Encontrar Antecessor
e Remover Elemento
120
100
150
30
35
no
noAnt 100
100
150
30
35
no
noAnt’
noAnt
int main() {
ARVORE arv;
inicializarArvore(&arv);
...
mostrar(arv.raiz);
remover(120, &arv);
 Remover 120:
Encontrar Antecessor
e Remover Elemento
100
100
150
30
35
no
noAnt’
100
150
30
35
no
noAntnoAnt
int main() {
ARVORE arv;
inicializarArvore(&arv);
...
mostrar(arv.raiz);
remover(120, &arv);
 Remover 120:
Encontrar Antecessor
e Remover Elemento
100
150
30
35
no
noAnt
[[[30.01.fb0]35.a2.fb-1]100.a3.fb-1[150.a1.fb0]]
int main() {
ARVORE arv;
inicializarArvore(&arv);
...
mostrar(arv.raiz);
remover(120, &arv);
 Criar uma função para remover um elemento da
árvore AVL, mantendo o balanceamento.
Remover Elemento
void remover(TIPOCHAVE chave, ARVORE* a){
// Remove chave da árvore.
a->raiz = removeNo(a->raiz, chave);
}
NO* removeNo(NO* no, TIPOCHAVE chave){
// Remove o nó com chave. 
// Reconstrói a árvore na volta da recursão.
...
}
NO* removeNo(NO* no, TIPOCHAVE chave){
if (!no){
printf("\nErro: a chave nao existe.");
return NULL;
}
// decidir em que lado procurar a chave
...
Remover Elemento
NO* removeNo(NO* no, TIPOCHAVE chave){
if (!no){
printf("\nErro: a chave nao existe.");
return NULL;
}
// decidir em que lado procurar a chave
if (chave < no->info)
no->esq = removeNo(no->esq, chave);
else if (no->info < chave)
no->dir = removeNo(no->dir, chave);
else
// remove nó com um filho ou folha
...
Remover Elemento
NO *removeNo(NO *no, TIPOCHAVE chave){
if (!no){
printf("\nErro: a chave nao existe.");
return NULL;
}
// decidir em que lado procurar a chave
if (chave < no->info)
no->esq = removeNo(no->esq, chave);
else if (no->info < chave)
no->dir = removeNo(no->dir, chave);
else
// remove nó folha 
if (!no->dir && !no->esq) 
no = NULL;
//remove nó com um filho
else if (!no->dir)
no = no->esq;
else if (!no->esq)
no = no->dir;
...
Remover 
Elemento
Remover 
Elemento
NO *removeNo(NO *no, TIPOCHAVE chave){
if (!no){
printf("\nErro: a chave nao existe.");
return NULL;
}
// decidir em que lado procurar a chave
if (chave < no->info)
no->esq = removeNo(no->esq, chave);
else if (no->info < chave)
no->dir = removeNo(no->dir, chave);
else
// remove nó folha 
if (!no->dir && !no->esq) 
no = NULL;
//remove nó com um filho
else if (!no->dir)
no = no->esq;
else if (!no->esq)
no = no->dir;
...
else //remove nó com dois filhos
no->esq = antecessor(&no, no->esq);
...
NO *removeNo(NO *no, TIPOCHAVEchave){
if (!no){
printf("\nErro: a chave nao existe.");
return NULL;
} // decidir em que lado procurar a chave
if (chave < no->info)
no->esq = removeNo(no->esq, chave);
else if (no->info < chave)
no->dir = removeNo(no->dir, chave);
else
// remove nó com um filho ou folha
if (!no->dir && !no->esq)
no = NULL;
else if (!no->dir) //remove nó com um filho
no = no->esq;
else if (!no->esq)
no = no->dir;
else //remove nó com dois filhos
no->esq = antecessor(&no, no->esq);
Remover 
Elemento
if(no){
no = calculaAlturaFB(no);
if(no->fb == 2 || no->fb == -2)
no = balancear(no);
}
return no;
}
NO *removeNo(NO *no, TIPOCHAVE chave){
if (!no) return NULL;
if (chave < no->info)
no->esq = removeNo(no->esq, chave);
else if (no->info < chave)
no->dir = removeNo(no->dir, chave);
else
if (!no->dir && !no->esq)
no = NULL;
else if (!no->dir)
no = no->esq;
else if (!no->esq)
no = no->dir;
else
no->esq = antecessor(&no, no->esq);
if(no){
no = calculaAlturaFB(no);
if(no->fb == 2 || no->fb == -2)
no = balancear(no);
}
return no;
}
Remover 
Elemento
Encontrar Antecessor
NO* antecessor(NO** no, NO* noAnt){
// Procura pelo nó antecessor de no 
// e remove o antecessor.
ALGORITMO
}
NO* antecessor(NO** no, NO* noAnt){
// desce até o nó mais à direita na subarvore esquerda
if (noAnt->dir)
noAnt->dir = antecessor(no, noAnt->dir);
else{ // copia a informação do antecessor para o nó removido
(*no)->info = noAnt->info;
// remove o antecessor
noAnt = noAnt->esq;
}
// reconstroi a subárvore na volta da recursão
if(noAnt){
noAnt = calculaAlturaFB(noAnt);
if(noAnt->fb == 2 || noAnt->fb == -2){
noAnt = balancear(noAnt);
}
}
return noAnt;
}
Encontrar Antecessor

Outros materiais