0 - PUC-Rio

Propaganda
 INF 1010
Estruturas de Dados Avançadas
Árvores AVL
10/10/12
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
1
Árvores
Balanceadas
10/10/12
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
2
Balanceamento de
Árvores Binárias de Busca
Motivação:
busca em O(log(n))
Estratégia:
diminuir a diferença de altura entre
a sub-árvore à esquerda e
a sub-árvore à direita
de cada nó
10/10/12
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
3
1922
1921
Árvore binária de busca construída de tal modo que
em todos seus nós, a altura de sua sub-árvore à
direita difere da altura da sub-árvore à esquerda de
no máximo 1 unidade
10/10/12
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
4
Fator de balanceamento
Fator de balanceamento de um nó
fb = hd – he
onde he = altura da sub-árvore à esquerda
hd = altura da sub-árvore à direita
struct _avl { int chave; int fb; /*fator de balanceamento*/ struct _avl *pai; struct _avl *esq; struct _avl *dir; }; 10/10/12
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
5
Árvore AVL – desequilíbrio (caso 1a)
árvore balanceada (equilibrada)
-1
0
0
2
0
4
0
desequilíbrio após inserir 1
8
10
6
desequilíbrio após inserir 3
-2
-2
8
-1
-1
0
10/10/12
1
0
4
-1
10
0
2
8
6
0
4
1
10
0
2
6
0
3
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
6
Árvore AVL – Caso 1a: rotação à direita
-2
0
r
t
-1
nova raiz
h+1
0
t
r
sad h
m
h
h+1
h+1
sad
h
h
m
static Avl* rotacao_direita(Avl *r) { Avl *pai=r-­‐>pai, *t=r-­‐>esq, *m=t-­‐>dir; t-­‐>dir = r; r-­‐>pai = t; r-­‐>esq = m; if (m) m-­‐>pai = r; t-­‐>pai = pai; if (pai) { if (pai-­‐>dir == r) pai-­‐>dir = t; else pai-­‐>esq = t; } t-­‐>fb = r-­‐>fb = 0; return t; } 10/10/12
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
7
Caso 1a - Exemplo de rotação à direita
-2
0
c
b
-1
b
0
0
a
c
0
a
Uma rotação à direita þ
10/10/12
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
8
Caso 1a - Exemplo de rotação à direita
árvore balanceada (equilibrada)
-1
0
0
2
0
4
0
8
10
6
-2
8
-1
4
-1
0
1
0
4
10
0
2
0
-1
6
0
2
0
1
0
6
8
0
10
Uma rotação à direita þ
10/10/12
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
9
Árvore AVL – desequilíbrio (caso 1b)
árvore balanceada (equilibrada)
1
0
8
0
4
0
desequilíbrio após inserir 11
9
10
0
12
desequilíbrio após inserir 13
2
2
8
0
8
1
4
0
0
10
-1
9
12
1
4
10
0
9
0
11
10/10/12
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
1
12
0
13
10
Árvore AVL – Caso 1b: rotação à esquerda
2
0
r
h
t
1
t
sae
h
m
r
nova raiz
h+1
h+1
h
sae
0
h+1
h
m
static Avl* rotacao_esquerda(Avl *r) { Avl *pai=r-­‐>pai, *t=r-­‐>dir, *m=t-­‐>esq; t-­‐>esq = r; r-­‐>pai = t; r-­‐>dir = m; if (m) m-­‐>pai = r; t-­‐>pai = pai; if (pai) { if (pai-­‐>dir == r) pai-­‐>dir = t; else pai-­‐>esq = t; } t-­‐>fb = r-­‐>fb = 0; return t; } 10/10/12
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
11
Caso 1b - Exemplo de rotação à esquerda
2
0
a
b
1
0
b
0
0
a
c
c
Uma rotação à esquerda þ
10/10/12
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
12
Árvore AVL – Casos simples: fb com mesmo sinal
-2
1a
0
r
t
-1
nova raiz
0
t
h+1
m
h+1
r
sad h
h
h+1
h
sad
h
m
1b
0
2
r
h
t
1
t
sae
h
m
nova raiz
h+1
h+1
r
h
sae
0
h+1
h
m
10/10/12
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
13
Exemplo: caso em que rotação simples não resolve
-2
r
r
c
-2
a
c
1
t
1
a
c
0
b
t
b
m
a
0
b
m
Não resolve!
10/10/12
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
14
Caso 2a - Balanceamento com rotação dupla
Uma rotação à direita na sub-árvore à direita…
2
0
a
a
b
-1
c
b
0
0
b
0
a
c
c
…seguida de uma rotação à esquerda
10/10/12
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
15
Caso 2a – Rotação direita-esquerda
2
r
r
t
T1
s
T2
-1
T3
s
T1
T4
s
r
t
T2
T3
T1
t
T2
T3
T4
T4
Avl* avl_rotacao_direita_esquerda(Avl *r) {
Avl *t = r->dir, *s = t->esq;
Avl *T2 = s->esq, *T3 = s->dir;
s->esq = r;
s->dir = t;
r->dir = T2;
t->esq = T3;
r->fb = (s->fb==1) ? -1 : 0;
( Explicação a seguir )
t->fb = (s->fb==-1) ? 1 : 0;
s->fb = 0;
return s;
}
10/10/12
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
16
Caso 2a.1 – Rotação direita-esquerda
2
0
r
s
t
T1
s
T2
-1
-1
0
r
t
1
T4
T1
T2
T3
T4
h
h-1
h
h
T3
Avl* avl_rotacao_direita_esquerda(Avl *r) {
Avl *t = r->dir, *s = t->esq;
Avl *T2 = s->esq, *T3 = s->dir;
s->esq = r;
s->dir = t;
r->dir = T2;
t->esq = T3;
r->fb = (s->fb==1) ? -1 : 0;
t->fb = (s->fb==-1) ? 1 : 0;
s->fb = 0;
return s;
}
10/10/12
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
17
Caso 2a.2 – Rotação direita-esquerda
2
0
r
s
t
T1
s
T2
0
-1
1
r
t
-1
T4
T1
T2
T3
T4
h
h
h-1
h
T3
Avl* avl_rotacao_direita_esquerda(Avl *r) {
Avl *t = r->dir, *s = t->esq;
Avl *T2 = s->esq, *T3 = s->dir;
s->esq = r;
s->dir = t;
r->dir = T2;
t->esq = T3;
r->fb = (s->fb==1) ? -1 : 0;
t->fb = (s->fb==-1) ? 1 : 0;
s->fb = 0;
return s;
}
10/10/12
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
18
Caso 2a.3 – Rotação direita-esquerda
2
0
r
s
t
T1
s
T2
0
-1
0
r
t
0
T4
T1
T2
T3
T4
h
h
h
h
T3
Avl* avl_rotacao_direita_esquerda(Avl *r) {
Avl *t = r->dir, *s = t->esq;
Avl *T2 = s->esq, *T3 = s->dir;
s->esq = r;
s->dir = t;
r->dir = T2;
t->esq = T3;
r->fb = (s->fb==1) ? -1 : 0;
t->fb = (s->fb==-1) ? 1 : 0;
s->fb = 0;
return s;
}
10/10/12
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
19
Caso 2b - Balanceamento com rotação dupla
Uma rotação à esquerda na sub-árvore à esquerda…
-2
0
c
c
b
1
b
a
0
a
0
b
0
c
a
…seguida de uma rotação à direita
10/10/12
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
20
Caso 2b – Rotação esquerda-direita
-2
r
1
r
p
q
T4
q
T1
T2
p
T3
T1
q
p
T4
T3
T1
r
T2
T3
T4
T2
Avl* avl_rotacao_direita_esquerda(Avl *r) {
Avl *p = r->esq, *q = p->dir;
Avl *T2 = q->esq, *T3 = q->dir;
q->esq = p;
q->dir = r;
p->dir = T2;
r->esq = T3;
p->fb = (q->fb==1) ? -1 : 0;
( Explicação a seguir )
r->fb = (q->fb==-1) ? 1 : 0;
q->fb = 0;
return q;
}
10/10/12
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
21
Caso 2b.1 – Rotação esquerda-direita
-2
0
r
1
q
-1
p
1
T1
T2
p
T4
q
0
r
T1
T2
T3
T4
h
h-1
h
h
T3
Avl* avl_rotacao_direita_esquerda(Avl *r) {
Avl *p = r->esq, *q = p->dir;
Avl *T2 = q->esq, *T3 = q->dir;
q->esq = p;
q->dir = r;
p->dir = T2;
r->esq = T3;
p->fb = (q->fb==1) ? -1 : 0;
r->fb = (q->fb==-1) ? 1 : 0;
q->fb = 0;
return s;
}
10/10/12
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
22
Caso 2b.2 – Rotação esquerda-direita
-2
0
r
1
q
0
p
-1
T1
T2
p
T4
q
1
r
T1
T2
T3
T4
h
h
h-1
h
T3
Avl* avl_rotacao_direita_esquerda(Avl *r) {
Avl *p = r->esq, *q = p->dir;
Avl *T2 = q->esq, *T3 = q->dir;
q->esq = p;
q->dir = r;
p->dir = T2;
r->esq = T3;
p->fb = (q->fb==1) ? -1 : 0;
r->fb = (q->fb==-1) ? 1 : 0;
q->fb = 0;
return s;
}
10/10/12
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
23
Caso 2b.3 – Rotação esquerda-direita
-2
0
r
1
q
0
p
0
T1
T2
p
T4
q
0
r
T1
T2
T3
T4
h
h
h
h
T3
Avl* avl_rotacao_direita_esquerda(Avl *r) {
Avl *p = r->esq, *q = p->dir;
Avl *T2 = q->esq, *T3 = q->dir;
q->esq = p;
q->dir = r;
p->dir = T2;
r->esq = T3;
p->fb = (q->fb==1) ? -1 : 0;
r->fb = (q->fb==-1) ? 1 : 0;
q->fb = 0;
return s;
}
10/10/12
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
24
Inserção
10/10/12
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
25
Inserção à esquerda
antes da inserção
1
-1
0
r
-2
r
r
r
-1
t
após a inserção
0
r
rotação direita
-2
-1
r
r
-2
r
1
t
balanceado
10/10/12
balanceado
(mas pode ter
desbalanceado
acima)
desbalanceado
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
r. esquerda-direita
26
static Avl* avl_insere2(Avl* r,int chave, int* flag) {
if (r==NULL) {
r = (Avl*) malloc(sizeof(Avl));
r->esq = r->dir = NULL;
r->chave = chave;
r->fb = 0;
*flag = 1;
}
else if (r->chave > chave) {
r->esq = avl_insere2 (r->esq, chave, flag);
if
if (*flag)
(*flag) {…
/* r cresceu à esquerda (ou seja, he aumentou)*/
}
switch(r->fb) { /* análise do fator de balanceamento de r */
1: /* antes:
hd>he {xxx depois: hd=he pois he aumentou */
else if case
(r->chave
< chave)
= 0; *flag(r->dir,
= 0; break;
r->dirr->fb
= avl_insere2
chave, flag);
case 0:… /* antes: hd=he xxx depois: hd<he pois he aumentou */
if (*flag)
r->fb = -1; break;
}
case -1: /* antes: hd<he xxx depois: hd-he=-2 pois he aumentou */
return r;if (r->esq->fb == -1) r = avl_rotacao_direita(r);
}
else r = avl_rotacao_esquerda_direita(r);
Avl* avl_insere(Avl*
r, int chave) {
*flag = 0; break;
int }flag=0;
}
return
avl_insere2 (r,chave,&flag);
}
10/10/12
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
27
Animação de Árvores AVL
http://www.strille.net/works/media_technology_projects/avl-tree_2001/
10/10/12
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
28
Remoções
• 
Problemas
•  semelhantes aos das inserções, ou seja,
pode ocorrer desbalanceamento
• 
Casos:
•  Caso 1: o nó removido é
uma folha ou tem apenas 1 descendente
•  Caso 2: o nó removido possui
as duas sub-árvores
10/10/12
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
29
Exemplo: Remove 4
5
5
3
2
1
8
4
7
6
3
10
9
8
2
11
7
1
10
6
9
11
rotação à direita
5
8
2
1
7
3
6
10/10/12
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
10
9
11
30
Exemplo: Remove 8
5
5
8
2
1
7
3
6
10/10/12
10
9
7
2
1
3
6
11
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
10
9
11
31
Exemplo: Remove 6
5
5
7
2
1
3
6
10
9
7
2
1
10
3
11
9
11
rotação à esquerda
5
2
1
10
3
7
11
9
10/10/12
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
32
Problemas com as Árvores AVL
• 
Problema:
•  Nem sempre uma ÚNICA rotação simples
(ou dupla) resolve o problema de
desbalanceamento dos nós
•  Há casos em que O(log n) rotações sào
necessárias para tornar a árvore balanceada
• 
Exemplo (a seguir):
•  exclusão do nó d provoca diversas rotações
10/10/12
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
34
Múltiplas Rotações na Árvore AVL
rotação dupla
5
5
9
3
1
4
11
7
9
3
8
2
5
10
1
12
6
8
2
7
11
10
9
2
1
3
8
12
7
9
8
7
12
8
2
3
10
6
6
5
1
11
5
rotação dupla
11
10
9
2
12
1
7
3
6
11
10
12
6
10/10/12
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
35
Esboço do algoritmo de remoção
• 
Pesquise o nó que contém a chave procurada, aplicando
recursivamente o algoritmo de remoção
• 
Quando achar o nó
•  faça a remoção como na árvore de busca binária
•  analise o balanceamento
•  Se o nó estiver desbalanceado ( |fb| >1 ),
faça as devidas rotações
• 
Recursivamente, reporte uma mudança de altura
de um nó ao seu pai para que ele faça as devidas correções
10/10/12
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
36
Esboço do algoritmo de remoção
• 
Pontos adicionais da remoção
(que não ocorrem na inserção)
•  É necessário tratar todos os casos de alturas
possíveis nas rotações
•  É necessário analisar quando
uma sub-árvore muda de altura
para reportar esta informação ao pai
10/10/12
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
37
Casos de rotação à esquerda (a s.a.e. perdeu altura)
2
2
r
2
r
t
T1
r
1
t
T1
m
rotação à esquerda
0
-1
t
t
0
1
r
r
T4
T1
10/10/12
m
T4
T1
m
s
T4
rotação à esquerda
0
t
T1
m
T4
rotação dupla
T2
-1
T4
T3
static Avl* rot_esquerda(Avl *r) {
Avl *t=r->dir, *m=t->esq;
t->esq = r;
r->dir = m;
if (t->fb==1) {
t->fb = 0; r->fb = 0; }
else
{
t->fb = -1; r->fb= 1; }
return t;
}
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
38
Rotação dupla direita-esquerda (fb=2)
2
r
r
r
t
T1
s
T2
-1
t
T1
-1
s
T4
T3
T2
0
T1
0
s
T2
1
T3
T3
s
0
r
T4
T1
-1
t
T2
T4
0
0
t
-1
1
T4
s
r
10/10/12
t
0
0
T2
-1
T3
s
T1
2
2
T3
0
r
T4
T1
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
t
T2
T3
T4
39
static Avl* rotacao_direita_esquerda(Avl *r) {
Avl *t=r->dir,*s=t->esq,*T2=s->esq,*T3=s->dir;
s->esq = r;
s->dir = t;
r->dir = T2;
t->esq = T3;
switch (s->fb){
case -1:
r->fb = s->fb = 0;
t->fb = 1; break;
case 0:
r->fb = s->fb = t->fb = 0; break;
case 1:
r->fb = -1;
s->fb = t->fb = 0; break;
}
return s;
}
10/10/12
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
40
Casos de rotação à direita (a s.a.d. perdeu altura)
-2
-2
r
-1
r
0
t
T4
m
T1
-2
rotação à direita
r
1
t
T4
m
T1
1
t
t
0
-1
r
r
T1
T1
m
10/10/12
T4
m
p
T4
T4
q
T1
rotação à direita
0
rotação dupla
T2
T3
static Avl* rot_direita(Avl *r) {
Avl *t=r->esq, *m=t->dir;
t->dir = r;
r->esq = m;
if (t->fb == -1) {
t->fb = 0; r->fb = 0; }
else
{
t->fb = 1; r->fb = -1; }
return t;
}
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
41
Rotação dupla esquerda-direita (fb=-2)
-2
r
1
1
T4
1
p
T1
T2
T3
q
T3
0
q
1
p
10/10/12
q
T2
0
0
T3
q
0
r
T2
T1
T3
q
T1
T4
1
T2
0
p
T4
0
q
T1
r
r
p
-1
-2
-2
0
p
T4
T1
-1
r
T2
T3
0
p
T4
T1
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
r
T2
T3
T4
42
static Avl* rotacao_esquerda_direita(Avl *r) {
Avl *p=r->esq,*q=p->dir,*T2=q->esq,*T3=q->dir;
q->esq = p;
q->dir = r;
p->dir = T2;
r->esq = T3;
switch (q->fb){
case -1:
r->fb = 1;
q->fb = p->fb = 0; break;
case 0:
r->fb = q->fb = p->fb = 0; break;
case 1:
r->fb = q->fb = 0;
p->fb = -1; break;
}
return q;
}
10/10/12
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
43
static Avl* avl_remove2(Avl *r, int chave, int *delta_h) {
if (!r) return NULL;
else if (chave < r->chave) {
r->esq = avl_remove2(r->esq, chave, delta_h);
r->fb -= *delta_h;
if (r->fb == 2) {
if (r->dir->fb == 1)
{ r=rotacao_esquerda(r); *delta_h =-1; }
else if (r->dir->fb == 0) { r=rotacao_esquerda(r); *delta_h = 0; }
else if (r->dir->fb == -1)
{ r=rotacao_direita_esquerda(r); *delta_h=-1; }
}
else *delta_h=((r->fb==1) ? 0 : -1); /*a sad mantém a altura do nó*/
}
else if (chave > r->chave) { /* caso simétrico */ }
else { /* achou o nó para remover – remoção semelhante à abb */
if (r->esq == NULL && r->dir == NULL) /* nó folha */
{ free(r); *delta_h = -1; r = NULL; }
else if (r->dir == NULL)
/* só um filho, à esquerda */
…
}
return r;
}
Avl* avl_remove(Avl *r, int chave) {
int delta_h = 0;
return avl_remove2(r, chave, &delta_h);
}
10/10/12
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
44
Relação entre altura e número de nós numa AVL
0
Seja N(h) o número mínimo de nós de uma AVL de altura h.
Então, no mínimo, temos uma das sub-árvores de altura h-1;
a outra teria que ter, no mínimo, h-2.
N (h) = N (h − 1) + N (h − 2) + 1
[N (h) +1] = [N (h −1) +1]+ [N (h − 2) +1]
[N (h) +1] =
são números de Fibonacci
1 ⎛ 1 + 5 ⎞
⎜
⎟
N ( h) + 1 ≈
⎜
5 ⎝ 2 ⎟⎠
0
h +3
h-1 h-2
h-2
h
h-1
h-2
h ≈ 1.44 log(n))
10/10/12
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
45
TAD avl.h
typedef struct _avl Avl;
Avl* avl_create(int (*pcomp)(const void*,const void*), void (*pfree)(void*));
Avl* avl_free(Avl* tree);
void avl_insert(Avl* tree, void* pinfo);
void avl_remove (Avl* tree, void* pinfo);
void* avl_first (Avl* tree);
void* avl_next(Avl* tree);
10/10/12
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
46
TAD avl.c (1)
typedef struct _avl_node AvlNode;
struct _avl_node {
void* info;
int
fb;
/* balance factor = hr - hl */
AvlNode* parent;
AvlNode* left;
AvlNode* right;
};
struct _avl {
AvlNode* root;
AvlNode* current;
int (*pcompare)(const void*,const void*);
void (*pfree)(void*);
};
10/10/12
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
47
TAD avl.c (2)
static AvlNode* rotate_right(AvlNode *r) {
AvlNode *parent=r->parent, *t=r->left, *m=t->right;
t->right = r; r->parent = t;
r->left = m; if (m) m->parent = r;
t->parent = parent; if (parent) {
if (parent->right == r) parent->right = t;
else
parent->left = t;
}
if (t->fb==-1) { t->fb = 0; r->fb = 0; }
else
{ t->fb = 1; r->fb =-1; }
return t;
}
10/10/12
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
48
TAD avl.c (3)
static AvlNode* rotate_right_left(AvlNode *r) {
AvlNode *parent=r->parent,*t=r->right,*s=t->left,*T2=s->left,*T3=s->right;
s->left = r; r->parent = s;
s->right = t; t->parent = s;
r->right = T2; if (T2) T2->parent = r;
t->left = T3; if (T3) T3->parent = t;
s->parent = parent; if (parent) {
if (parent->right == r) parent->right = s;
else
parent->left = s;
}
switch (s->fb){
case -1: r->fb=s->fb=0; t->fb=1; break;
case 0: r->fb=s->fb=t->fb=0; break;
case 1: r->fb=-1; s->fb=t->fb=0; break;
}
return s;
}
10/10/12
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
49
static AvlNode* insert(Avl* tree, AvlNode* r, void* info, int* delta_h) {
if (r==NULL) {
r = (AvlNode*) malloc(sizeof(AvlNode));
r->left = r->right = r->parent = NULL;
r->info = info; r->fb = 0; *delta_h = 1;
}
else if (tree->pcompare(info,r->info)<0) {
r->left = insert(tree,r->left,info,delta_h);
if (r->left) r->left->parent = r;
if (*delta_h) {
switch(r->fb){
case 1: r->fb = 0; *delta_h = 0; break;
case 0: r->fb = -1; break;
case -1: if (r->left->fb == -1)
r = rotate_right(r);
else
r = rotate_left_right(r);
*delta_h = 0;
break;
}
}
}
else if (tree->pcompare(info,r->info)>0) {
...........
return r;
}
TAD avl.c (4)
10/10/12
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
50
static AvlNode* remove_node(Avl* tree, AvlNode *r, void* info, int *delta_h) {
if (!r) return NULL;
else if (tree->pcompare(info,r->info)<0) {
r->left = remove_node(tree,r->left, info, delta_h);
if (r->left) r->left->parent=r;
if (*delta_h==-1){
r->fb++;
if (r->fb==2){
switch (r->right->fb){
case 1: { r=rotate_left(r);
*delta_h=-1; break; }
case 0: { r=rotate_left(r);
*delta_h= 0; break; }
case -1: { r=rotate_right_left(r); *delta_h=-1; break; }
}
}
else
*delta_h=(r->fb==1)?0:-1; /* right sub-tree can sustain the node height */
}
}
else if (tree->pcompare(info,r->info)>0) {
TAD avl.c (5)
.........
10/10/12
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
51
.........
TAD avl.c (6)
}
else { /* found node to be removed */
if (r->left==NULL && r->right==NULL) /* leaf */
{ if (tree->pfree) tree->pfree(r->info); free(r); *delta_h=-1; r = NULL; }
else if (r->right == NULL) /* only left child */
{ AvlNode* t = r; r = r->left; if (tree->pfree) tree->pfree(t->info); free(t);
*delta_h=-1; }
else if (r->left == NULL) /* only right child */
{ AvlNode* t = r; r = r->right; if (tree->pfree) tree->pfree(t->info); free(t);
*delta_h=-1; }
else { /* two children */
AvlNode *r0=r, *successor = r->right;
void* info2;
while (successor->left !=NULL) successor = successor->left;
info2 = successor->info;
r = remove_node(tree,r,info2,delta_h);
r0->info = info2;
}
}
return r;
}
10/10/12
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
52
TAD avl.c (7)
void* avl_next(Avl *tree) {
if (tree==NULL) return NULL;
else {
AvlNode* node = tree->current;
if (node==NULL) return NULL;
else if (node->right!=NULL) { /* returns min of right sub-tree */
node=node->right;
while(node->left!=NULL) node=node->left;
tree->current=node;
return node->info;
} else { /* returns the nearest ancestor that is larger than its child */
AvlNode* p = node->parent;
while ( p!=NULL && node==p->right ) {
node = p;
p = p->parent;
}
tree->current=p;
return (p!=NULL)?p->info:NULL;
}
}
}
10/10/12
© 2012 DI, PUC-Rio • Estruturas de Dados Avançadas • 2012.2
53
Download