Você está na página 1de 34

RVORES AVL

Lvia N. Andrade

rvores AVL

Recebem esse nome em homenagem aos seus criadores,


os matemticos russos AdelsonVelskii e Landis, 1962.

Uma rvore AVL uma rvore binria de pesquisa onde a


diferena em altura entre as subrvore esquerda e direita
no mximo 1 (positivo ou negativo).

Quando a diferena chega a 2 ou 2, deve ser refeito o


balanceamento atravs de rotaes.

Chamamos essa diferena de fator de balanceamento.

Descrio das rotaes


Diferena de
altura de um
n

-2

Diferena de altura do
n filho do n
desbalanceado

Tipo de rotao

Simples esquerda

Simples esquerda

-1

Dupla com filho para


a direita e pai para a
esquerda

Dupla com filho para


a esquerda e pai para
a direita

Simples direita

-1

Simples direita

Exemplos de Balanceamento
Rotao simples esquerda

rvore Balanceada

rvore
Desbalanceada
2

+ 12

12
rvore
Balanceada

Rotao simple
para a esquerd

8
0

12

Cdigo em C
// n desbalanceado = 2

void rebalanceamentoEsq (Apontador *p, int *h) {


Apontador pu = (*p)->Dir; //passando para filho do n desbalanceado
if (pu->balanceamento == 1) { //n filho = 1, mesmo sinal rotao
simples a esquerda

printf("rotacao a esquerda com %ld\n", pu->Reg.Chave);


(*p)->Dir = pu->Esq; //direita de p aponta para null
pu->Esq = (*p);
(*p)->balanceamento = 0;
(*p) = pu;
}

pu

(*p)->balanceamento = 0;
(*h) = 0;
}

12

Cdigo em C
// n desbalanceado = 2

void rebalanceamentoEsq (Apontador *p, int *h) {


Apontador pu = (*p)->Dir; //passando para filho do n desbalanceado
if (pu->balanceamento == 1) { //n filho = 1, mesmo sinal rotao
simples a esquerda

printf("rotacao a esquerda com %ld\n", pu->Reg.Chave);


(*p)->Dir = pu->Esq; //direita de p aponta para null
pu->Esq = (*p); //p passa a ser filho a esquerda de pu
(*p)->balanceamento = 0;
(*p) = pu;
}

pu

(*p)->balanceamento = 0;
(*h) = 0;
}

12

Cdigo em C
// n desbalanceado = 2

void rebalanceamentoEsq (Apontador *p, int *h) {


Apontador pu = (*p)->Dir; //passando para filho do n desbalanceado
if (pu->balanceamento == 1) { //n filho = 1, mesmo sinal rotao
simples a esquerda

printf("rotacao a esquerda com %ld\n", pu->Reg.Chave);


(*p)->Dir = pu->Esq; //direita de p aponta para null
pu->Esq = (*p); //p passa a ser filho a esquerda de pu
(*p)->balanceamento = 0; //atualiza FB de p
(*p) = pu;
}

pu

(*p)->balanceamento = 0;
(*h) = 0;
}

12

Cdigo em C
// n desbalanceado = 2

void rebalanceamentoEsq (Apontador *p, int *h) {


Apontador pu = (*p)->Dir; //passando para filho do n desbalanceado
if (pu->balanceamento == 1) { //n filho = 1, mesmo sinal rotao
simples a esquerda

printf("rotacao a esquerda com %ld\n", pu->Reg.Chave);


(*p)->Dir = pu->Esq; //direita de p aponta para null
pu->Esq = (*p); //p passa a ser filho a esquerda de pu
(*p)->balanceamento = 0; //atualiza FB de p
(*p) = pu; //pu agora p
}

(*p)->balanceamento = 0; //atualiza FB de p
(*h) = 0;
}

12

Descrio das rotaes


Diferena de
altura de um
n

-2

Diferena de altura do
n filho do n
desbalanceado

Tipo de rotao

Simples esquerda

Simples esquerda

-1

Dupla com filho para


a direita e pai para a
esquerda

Dupla com filho para


a esquerda e pai para
a direita

Simples direita

-1

Simples direita

Rotao dupla com filho para a direita e


pai para a esquerda
rvore Balanceada

Rotao para a
direita no filho do
n
desbalanceado

rvore Balanceada

7
6

+7

rvore
Desbalanceada
2

7
0

Rotao para
a esquerda no
n
desbalancead

rvore

-1

// n desbalanceado = 2

void rebalanceamentoDirEsq (Apontador *p, int *h) {


Apontador pu = (*p)->Dir; //passando para filho do n desbalanceado
if (pu->balanceamento == -1) { //n filho = -1, sinal diferente rotao
dupla com pai para esquerda e filho para direita

Apontador pv = pu->Esq;
printf("rotacao dupla direita-esquerda com %ld\n", pv>Reg.Chave);
pu->Esq = pv->Dir;

pv->Dir = pu;

(*p)->Dir = pv->Esq; pv->Esq = (*p);


if (pv->balanceamento == 1) (*p)->balanceamento = -1;
else (*p)->balanceamento = 0;
if (pv->balanceamento == -1) pu->balanceamento = 1;
else pu->balanceamento = 0;
(*p) = pv;

pu

(*p)->balanceamento = 0;
(*h) = 0;

7 pv

-1

// n desbalanceado = 2

void rebalanceamentoDirEsq (Apontador *p, int *h) {


Apontador pu = (*p)->Dir; //passando para filho do n desbalanceado
if (pu->balanceamento == -1) { //n filho = -1, sinal diferente rotao
dupla com pai para esquerda e filho para direita

Apontador pv = pu->Esq;
printf("rotacao dupla direita-esquerda com %ld\n", pv>Reg.Chave);
pu->Esq = pv->Dir;

pv->Dir = pu; //esq de pu aponta para null e pu se

torna filho direito de pv

(*p)->Dir = pv->Esq; pv->Esq = (*p);


if (pv->balanceamento == 1) (*p)->balanceamento = -1;
else (*p)->balanceamento = 0;
if (pv->balanceamento == -1) pu->balanceamento =21;
else pu->balanceamento = 0;

(*p) = pv;
}
(*p)->balanceamento = 0;
(*h) = 0;

pv

-1
pu

// n desbalanceado = 2

void rebalanceamentoDirEsq (Apontador *p, int *h) {


Apontador pu = (*p)->Dir; //passando para filho do n desbalanceado
if (pu->balanceamento == -1) { //n filho = -1, sinal diferente rotao dupla
com pai para esquerda e filho para direita

Apontador pv = pu->Esq;
printf("rotacao dupla direita-esquerda com %ld\n", pv->Reg.Chave);
pu->Esq = pv->Dir;

pv->Dir = pu; //esq de pu aponta para null e pu se

torna filho direito de pv

(*p)->Dir = pv->Esq; pv->Esq = (*p); //dir de p aponta para null e p se


torna filho esquerdo de pv

if (pv->balanceamento == 1) (*p)->balanceamento = -1;


else (*p)->balanceamento = 0;
if (pv->balanceamento == -1) pu->balanceamento = 1;
else pu->balanceamento = 0;
(*p) = pv;
}

pv

(*p)->balanceamento = 0;
(*h) = 0;
}

p 6

-1
pu

// n desbalanceado = 2

void rebalanceamentoDirEsq (Apontador *p, int *h) {


Apontador pu = (*p)->Dir; //passando para filho do n desbalanceado
if (pu->balanceamento == -1) { //n filho = -1, sinal diferente rotao dupla
com pai para esquerda e filho para direita

Apontador pv = pu->Esq;
printf("rotacao dupla direita-esquerda com %ld\n", pv->Reg.Chave);
pu->Esq = pv->Dir;

pv->Dir = pu; //esq de pu aponta para null e pu se

torna filho direito de pv

(*p)->Dir = pv->Esq; pv->Esq = (*p); //dir de p aponta para null e p se


torna filho esquerdo de pv

if (pv->balanceamento == 1) (*p)->balanceamento = -1;


else (*p)->balanceamento = 0; //atualiza FB de p
if (pv->balanceamento == -1) pu->balanceamento = 1;
else pu->balanceamento = 0;
(*p) = pv;
}

pv

(*p)->balanceamento = 0;
(*h) = 0;
}

p 6

-1
pu

// n desbalanceado = 2

void rebalanceamentoDirEsq (Apontador *p, int *h) {


Apontador pu = (*p)->Dir; //passando para filho do n desbalanceado
if (pu->balanceamento == -1) { //n filho = -1, sinal diferente rotao dupla
com pai para esquerda e filho para direita

Apontador pv = pu->Esq;
printf("rotacao dupla direita-esquerda com %ld\n", pv->Reg.Chave);
pu->Esq = pv->Dir;

pv->Dir = pu; //esq de pu aponta para null e pu se

torna filho direito de pv

(*p)->Dir = pv->Esq; pv->Esq = (*p); //dir de p aponta para null e p se


torna filho esquerdo de pv

if (pv->balanceamento == 1) (*p)->balanceamento = -1;


else (*p)->balanceamento = 0; //atualiza FB de p
if (pv->balanceamento == -1) pu->balanceamento = 1;
else pu->balanceamento = 0; //atualiza FB de pu
(*p) = pv;
}

pv

(*p)->balanceamento = 0;
(*h) = 0;
}

p 6

0
pu

// n desbalanceado = 2

void rebalanceamentoDirEsq (Apontador *p, int *h) {


Apontador pu = (*p)->Dir; //passando para filho do n desbalanceado
if (pu->balanceamento == -1) { //n filho = -1, sinal diferente rotao dupla
com pai para esquerda e filho para direita

Apontador pv = pu->Esq;
printf("rotacao dupla direita-esquerda com %ld\n", pv->Reg.Chave);
pu->Esq = pv->Dir;

pv->Dir = pu; //esq de pu aponta para null e pu se

torna filho direito de pv

(*p)->Dir = pv->Esq; pv->Esq = (*p); //dir de p aponta para null e p se


torna filho esquerdo de pv

if (pv->balanceamento == 1) (*p)->balanceamento = -1;


else (*p)->balanceamento = 0; //atualiza FB de p
if (pv->balanceamento == -1) pu->balanceamento = 1;
else pu->balanceamento = 0; //atualiza FB de pu
(*p) = pv; //pv agora p
}

(*p)->balanceamento = 0; //atualiza FB de p
(*h) = 0;
}

Descrio das rotaes


Diferena de
altura de um
n

-2

Diferena de altura do
n filho do n
desbalanceado

Tipo de rotao

Simples esquerda

Simples esquerda

-1

Dupla com filho para


a direita e pai para a
esquerda

Dupla com filho para


a esquerda e pai para
a direita

Simples direita

-1

Simples direita

Rotao dupla com filho para a esquerda


e pai para a direita
rvore Balanceada

6
0

rvore
Desbalanceada
-2

+5
1

Rotao para a
esquerda no filho
do n
desbalanceado

3
0

rvore Balanceada
0

-2

-1
0

Rotao para a
direita no n
desbalanceado

rvore

// n desbalanceado = -2

void rebalanceamentoEsqDir (Apontador *p, int *h) {


Apontador pu = (*p)->Esq; //passando para filho do n desbalanceado
if (pu->balanceamento == 1) { //n filho = 1, sinal diferente rotao
dupla com pai para esquerda e filho para direita

Apontador pv = pu->Dir;
printf("rotacao dupla esquerda-direita com %ld\n", pv>Reg.Chave);
pu->Dir = pv->Esq;

pv->Esq = pu;

(*p)->Esq = pv->Dir; pv->Dir = (*p);


if (pv->balanceamento == -1) (*p)->balanceamento = 1;
else (*p)->balanceamento = 0;
if (pv->balanceamento == 1) pu->balanceamento = -1;
else pu->balanceamento = 0;
(*p) = pv;
}

p
1

pu

(*p)->balanceamento = 0;
(*h) = 0;

0
pv

-2

// n desbalanceado = -2

void rebalanceamentoEsqDir (Apontador *p, int *h) {


Apontador pu = (*p)->Esq; //passando para filho do n desbalanceado
if (pu->balanceamento == 1) { //n filho = 1, sinal diferente rotao
dupla com pai para esquerda e filho para direita

Apontador pv = pu->Dir;
printf("rotacao dupla esquerda-direita com %ld\n", pv>Reg.Chave);
pu->Dir = pv->Esq;

pv->Esq = pu; //direita de pu aponta para null e pu

se torna filho esquerdo de pv

(*p)->Esq = pv->Dir; pv->Dir = (*p);


if (pv->balanceamento == -1) (*p)->balanceamento = 1;
else (*p)->balanceamento = 0;
if (pv->balanceamento == 1) pu->balanceamento = -1;
else pu->balanceamento = 0;
(*p) = pv;

}
(*p)->balanceamento = 0;
(*h) = 0;

1
pu

p
pv

-2

// n desbalanceado = -2

void rebalanceamentoEsqDir (Apontador *p, int *h) {


Apontador pu = (*p)->Esq; //passando para filho do n desbalanceado
if (pu->balanceamento == 1) { //n filho = 1, sinal diferente rotao dupla
com pai para esquerda e filho para direita

Apontador pv = pu->Dir;
printf("rotacao dupla esquerda-direita com %ld\n", pv->Reg.Chave);
pu->Dir = pv->Esq;

pv->Esq = pu; //direita de pu aponta para null e pu se

torna filho esquerdo de pv

(*p)->Esq = pv->Dir; pv->Dir = (*p);

//esquerda de p aponta para null e p se

torna filho direito de pv

if (pv->balanceamento == -1) (*p)->balanceamento = 1;


else (*p)->balanceamento = 0;
if (pv->balanceamento == 1) pu->balanceamento = -1;
else pu->balanceamento = 0;
(*p) = pv;
0

}
(*p)->balanceamento = 0;
(*h) = 0;
}

1
pu

pv

-2

// n desbalanceado = -2

void rebalanceamentoEsqDir (Apontador *p, int *h) {


Apontador pu = (*p)->Esq; //passando para filho do n desbalanceado
if (pu->balanceamento == 1) { //n filho = 1, sinal diferente rotao dupla
com pai para esquerda e filho para direita

Apontador pv = pu->Dir;
printf("rotacao dupla esquerda-direita com %ld\n", pv->Reg.Chave);
pu->Dir = pv->Esq;

pv->Esq = pu; //direita de pu aponta para null e pu se

torna filho esquerdo de pv

(*p)->Esq = pv->Dir; pv->Dir = (*p);

//esquerda de p aponta para null e p se

torna filho direito de pv

if (pv->balanceamento == -1) (*p)->balanceamento = 1;


else (*p)->balanceamento = 0;

//atualiza FB de p

if (pv->balanceamento == 1) pu->balanceamento = -1;


else pu->balanceamento = 0;
(*p) = pv;
0

}
(*p)->balanceamento = 0;
(*h) = 0;
}

1
pu

pv

// n desbalanceado = -2

void rebalanceamentoEsqDir (Apontador *p, int *h) {


Apontador pu = (*p)->Esq; //passando para filho do n desbalanceado
if (pu->balanceamento == 1) { //n filho = 1, sinal diferente rotao dupla
com pai para esquerda e filho para direita

Apontador pv = pu->Dir;
printf("rotacao dupla esquerda-direita com %ld\n", pv->Reg.Chave);
pu->Dir = pv->Esq;

pv->Esq = pu; //direita de pu aponta para null e pu se

torna filho esquerdo de pv

(*p)->Esq = pv->Dir; pv->Dir = (*p);

//esquerda de p aponta para null e p se

torna filho direito de pv

if (pv->balanceamento == -1) (*p)->balanceamento = 1;


else (*p)->balanceamento = 0;

//atualiza FB de p

if (pv->balanceamento == 1) pu->balanceamento = -1;


else pu->balanceamento = 0;

//atualiza FB de p

(*p) = pv;
0

}
(*p)->balanceamento = 0;
(*h) = 0;
}

0
pu

pv

// n desbalanceado = -2

void rebalanceamentoEsqDir (Apontador *p, int *h) {


Apontador pu = (*p)->Esq; //passando para filho do n desbalanceado
if (pu->balanceamento == 1) { //n filho = 1, sinal diferente rotao dupla
com pai para esquerda e filho para direita

Apontador pv = pu->Dir;
printf("rotacao dupla esquerda-direita com %ld\n", pv->Reg.Chave);
pu->Dir = pv->Esq;

pv->Esq = pu; //direita de pu aponta para null e pu se

torna filho esquerdo de pv

(*p)->Esq = pv->Dir; pv->Dir = (*p);

//esquerda de p aponta para null e p se

torna filho direito de pv

if (pv->balanceamento == -1) (*p)->balanceamento = 1;


else (*p)->balanceamento = 0;

//atualiza FB de p

if (pv->balanceamento == 1) pu->balanceamento = -1;


else pu->balanceamento = 0;
(*p) = pv;

//atualiza FB de p

//pv agora p

}
(*p)->balanceamento = 0; //atualiza FB de p
(*h) = 0;
}

Descrio das rotaes


Diferena de
altura de um
n

-2

Diferena de altura do
n filho do n
desbalanceado

Tipo de rotao

Simples esquerda

Simples esquerda

-1

Dupla com filho para


a direita e pai para a
esquerda

Dupla com filho para


a esquerda e pai para
a direita

Simples direita

-1

Simples direita

Exemplos de Balanceamento
Rotao simples direita
rvore Balanceada

8
0

rvore
Desbalanceada
-2

-1

+2
-1

6
0

rvore
Balanceada

0
0

6
8

Rotao simples
para a direita

Cdigo em C
// n desbalanceado = -2

void rebalanceamentoDir (Apontador *p, int *h) {


Apontador pu = (*p)->Esq; //passando para filho do n desbalanceado
if (pu->balanceamento == -1) { //n filho = -1, mesmo sinal rotao
simples a direita

printf("rotacao a direita com %ld\n", pu->Reg.Chave);


(*p)->Esq = pu->Dir;
pu->Dir = (*p);
(*p)->balanceamento = 0;

(*p) = pu;
}

-1

(*p)->balanceamento = 0;
(*h) = 0;
}

pu

-2

Cdigo em C
// n desbalanceado = -2

void rebalanceamentoDir (Apontador *p, int *h) {


Apontador pu = (*p)->Esq; //passando para filho do n desbalanceado
if (pu->balanceamento == -1) { //n filho = -1, mesmo sinal rotao
simples a direita

printf("rotacao a direita com %ld\n", pu->Reg.Chave);


(*p)->Esq = pu->Dir; //esquerda de p aponta para null
pu->Dir = (*p); //p passa a ser filho direito de pu
(*p)->balanceamento = 0;
(*p) = pu;

-1

}
(*p)->balanceamento = 0;
(*h) = 0;
}

6 pu
p

-2

Cdigo em C
// n desbalanceado = -2

void rebalanceamentoDir (Apontador *p, int *h) {


Apontador pu = (*p)->Esq; //passando para filho do n desbalanceado
if (pu->balanceamento == -1) { //n filho = -1, mesmo sinal rotao
simples a direita

printf("rotacao a direita com %ld\n", pu->Reg.Chave);


(*p)->Esq = pu->Dir; //esquerda de p aponta para null
pu->Dir = (*p); //p passa a ser filho direito de pu
(*p)->balanceamento = 0; //atualiza FB de p
(*p) = pu;

-1

}
(*p)->balanceamento = 0;
(*h) = 0;
}

6 pu
p

Cdigo em C
// n desbalanceado = -2

void rebalanceamentoDir (Apontador *p, int *h) {


Apontador pu = (*p)->Esq; //passando para filho do n desbalanceado
if (pu->balanceamento == -1) { //n filho = -1, mesmo sinal rotao
simples a direita

printf("rotacao a direita com %ld\n", pu->Reg.Chave);


(*p)->Esq = pu->Dir; //esquerda de p aponta para null
pu->Dir = (*p); //p passa a ser filho direito de pu
(*p)->balanceamento = 0; //atualiza FB de p
(*p) = pu; //pu agora p

}
(*p)->balanceamento = 0; //atualiza FB de p
(*h) = 0;
}

6 p
8

Exerccio 1

Considere a insero dos seguintes valores


(nesta ordem) em uma rvore AVL:
5,3,8,2,4,7,10,1,6,9,11. Para essas inseres
nenhuma rotao necessria. Desenhe a
rvore AVL resultante e determine o fator de
balanceamento de cada n.

Exerccio 2
Determinado sistema armazena registros por
chaves numricas em uma rvore AVL.
Nessa rvore so inseridos os seguintes
valores: 20,10,5,30,25,27 e 28 nessa
ordem.
Apresente passo a passo como a rvore vai
sendo construda. Realize as rotaes
necessrias e indique qual rotao foi
realizada em cada caso.

Resolvendo o Exerccio 2
1) Insero das chaves 20 e 10, nessa ordem

A rvore ficou pendendo para a esquerda


O fator de balanceamento do n cuja chave
20 -1.
O fator de uma folha sempre 0 (zero).

2) Continuar as inseres ...

Referncias Utilizadas

Livro:
ASCENCIO, A. F. G.; ARAJO, G. S. Estruturas de dados:
algoritmos, anlise da complexidade e implementaes
em Java e C/C++. So Paulo: Pearson Prentice Hall, 2010.

Cdigos de rvores AVL: Nvio Ziviane

Notas de aula da disciplina, disponvel no Moodle.

Você também pode gostar