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