Você está na página 1de 26

Tcnicas de Programao

(c) Paulo Santos


2
rvores Adelson-Velskii e Landis
Uma rvore AVL uma rvore de pesquisa
binria cujos algortimos de insero e remoo
fazem a rvore ficar sempre balanceada.
A diferena entre a sub-rvore esquerda e a sub-
rvore direita no mximo de um nvel.
(c) Paulo Santos
3
rvores AVL
Funes:
int insere(Arvore *a, int info);
int existe(Arvore *a, int info);
int remover(Arvore *a, int info);
(c) Paulo Santos
4
AVL - Representao
typedef struct _NodoArvore {
int dados;
int altura;
struct _ NodoArvore * esquerda;
struct _ NodoArvore * direita;
} Nodo;
typedef struct {
NodoArvore *raiz;
} Arvore;
(c) Paulo Santos
5
AVL Altura de um Nodo
(c)
6
AVL Factor de um Nodo
Diferena entre a altura do nodo esquerdo pela altura do
nodo direito. Se o nodo no existir a altura 0.
(c) Paulo Santos
7
AVL Factor de um Nodo
Se o Factor 0, o nodo est equilibrado.
Se o Factor 1, o nodo est pesado esquerda
Se o Factor -1, o nodo est pesado direita
Se o Factor for qualquer outro valor porque a rvore no est balanceada
int factor(NodoArvore *n) {
return altura(n->esquerda)-altura(n->direita);
}
A funo altura devolve 0 se o parmetro for nulo, caso contrario devolve a sua altura
do nodo.
int altura(NodoArvore *n) {
if (n == NULL)
return 0;
else
return n->altura;
}
(c) Paulo Santos
8
AVL Rotao simples direita
Sempre que um nodo fica com um factor
acima de 1 e o seu nodo esquerdo tem um
factor maior ou igual a 0 efectua-se uma
rotao simples direita
(c) Paulo Santos
9
AVL Rotao simples direita
NodoArvore* rotacaoDireita(NodoArvore *k2) {
NodoArvore *k1 = k2->esquerda;
k2->esquerda = k1->direita;
k1->direita = k2;
k2->altura = max(altura(k2->esquerda), altura(k2->direita)) + 1;
k1->altura = max(altura(k1->esquerda), altura(k2)) + 1;
return k1;
}
(c) Paulo Santos
10
AVL Rotao simples esquerda
Sempre que um nodo fica com um factor
abaixo de -1 e o seu nodo direito tem um
factor menor ou igual a 0 efectua-se uma
rotao simples esquerda
(c) Paulo Santos
11
AVL Rotao simples esquerda
NodoArvore* rotacaoEsquerda(NodoArvore *k1) {
NodoArvore *k2 = k1->direita;
k1->direita = k2->esquerda;
k2->esquerda = k1;
k1->altura = max(altura(k1->esquerda), altura(k1->direita)) + 1;
k2->altura = max(altura(k2->direita), altura(k1)) + 1;
return k2;
}
(c) Paulo Santos
12
AVL Rotao dupla direita
Sempre que um nodo fica com um factor
acima de 1 e o seu nodo esquerdo tem um
factor menor que 0 efectua-se uma rotao
dupla direita
(c) Paulo Santos
13
AVL Rotao dupla direita
NodoArvore* rotacaoDulplaDireita(NodoArvore *k3){
k3->esquerda = rotacaoEsquerda(k3->esquerda);
return rotacaoDireita(k3);
}
(c) Paulo Santos
14
AVL Rotao dupla esquerda
Sempre que um nodo fica com um factor
abaixo de -1 e o seu nodo direito tem um
factor maior que 1 efectua-se uma rotao
dupla esquerda
(c) Paulo Santos
15
AVL Rotao dupla esquerda
NodoArvore* rotacaoDulplaEsquerda(NodoArvore *k1){
k1->direita = rotacaoDireita(k1->direita);
return rotacaoEsquerda(k1);
}
(c) Paulo Santos
16
AVL - Insero
int insere(Arvore *a, int info){
NodoArvore *n = (NodoArvore*)malloc(sizeof(NodoArvore));
if (n == NULL)
return 0;
n->dados=info;
n->altura = 1;
n->esquerda = NULL;
n->direita = NULL;
if (a->raiz == NULL)
a->raiz = n;
else
a->raiz = __insere(a->raiz, n);
return 1;
}
(c) Paulo Santos
17
AVL - Insero
NodoArvore* __insere(NodoArvore *actual, NodoArvore *novo) {
if (novo->dados < actual->dados)
if (actual->esquerda == NULL)
actual->esquerda = novo;
else
actual->esquerda = __insere(actual->esquerda, novo);
else
if (actual->direita == NULL)
actual->direita = novo;
else
actual->direita = __insere(actual->direita, novo);
return balancear(actual);
}
(c) Paulo Santos
18
AVL - Balance
NodoArvore* balancear(NodoArvore *n){
n->altura = max(altura(n->esquerda), altura(n->direita))+1;
if (factor(n)>1) {
if (factor(n->esquerda)>=0)
n = rotacaoDireita(n);
else
n = rotacaoDulplaDireita(n);
} else if (factor(n)<-1) {
if (factor(n->direita)<=0)
n = rotacaoEsquerda(n);
else
n = rotacaoDulplaEsquerda(n);
}
return n;
}
(c) Paulo Santos
19
AVL - Remove
Guarda-se o caminho
numa pilha at
chegar ao nodo 75.
No final da remoo,
balanceia-se todos
os elementos da
pilha
(c) Paulo Santos
20
AVL - Remove
(c) Paulo Santos
21
AVL Remoo
int remover(Arvore *a, int info) {
NodoArvore *nodoARemover = a->raiz;
NodoArvore *pai = NULL;
Pilha *p = criaPilha();
push(p, a->raiz);
while (nodoARemover != NULL && nodoARemover->dados != info) {
pai = nodoARemover;
if (info < nodoARemover->dados)
nodoARemover = nodoARemover->esquerda;
else
nodoARemover = nodoARemover->direita;
push(p, nodoARemover);
}
if (nodoARemover == NULL) {
libertaPilha(p);
return 0;
} else {
(c) Paulo Santos
22
AVL Remoo
// arvore apenas com um elemento
if (a->raiz->esquerda == NULL && a->raiz->direita == NULL) {
free(a->raiz);
a->raiz = NULL;
} else if (a->raiz->esquerda == NULL && a->raiz->direita != NULL) {
a->raiz = a->raiz->direita;
free(nodoARemover);
} else if (a->raiz->esquerda != NULL && a->raiz->direita == NULL) {
a->raiz = a->raiz->esquerda;
free(nodoARemover);
} else
// caso 1: uma folha
if (nodoARemover->esquerda == NULL && nodoARemover->direita == NULL) {
if (nodoARemover->dados < pai->dados)
pai->esquerda = NULL;
else
pai->direita = NULL;
pop(p);
free(nodoARemover);
} else
(c) Paulo Santos
23
AVL Remoo
// caso 2.1: Tem apenas um filho direita
if (nodoARemover->esquerda == NULL && nodoARemover->direita != NULL) {
if (nodoARemover->dados < pai->dados)
pai->esquerda = nodoARemover->direita;
else
pai->direita = nodoARemover->direita;
pop(p);
push(p, nodoARemover->direita);
free(nodoARemover);
} else
// caso 2.2: Tem apenas um filho esquerda
if (nodoARemover->esquerda != NULL && nodoARemover->direita == NULL) {
if (nodoARemover->dados < pai->dados)
pai->esquerda = nodoARemover->esquerda;
else
pai->direita = nodoARemover->esquerda;
pop(p);
push(p, nodoARemover->esquerda);
free(nodoARemover);
}
(c) Paulo Santos
24
AVL Remoo
else { // caso 3: Tem dois filhos
NodoArvore *nodoMaior = nodoARemover->esquerda;
while (nodoMaior->direita != NULL)
nodoMaior = nodoMaior->direita;
NodoArvore *paiNodoMaior = procuraPai(a, nodoMaior->dados);
if (paiNodoMaior == nodoARemover)
paiNodoMaior->esquerda = nodoMaior->esquerda;
else
paiNodoMaior->direita = nodoMaior->esquerda;
nodoARemover->dados = nodoMaior->dados;
free(nodoMaior);
}
(c) Paulo Santos
25
AVL Remoo
while (!estaVazia(p)) {
NodoArvore *n = pop(p);
NodoArvore *pai = NULL;
if (!estaVazia(p))
pai = peek(p);
if (pai == NULL)
a->raiz = balancear(n);
else if (n->dados < pai->dados)
pai->esquerda = balancear(n);
else
pai->direita = balancear(n);
}
libertaPilha(p);
return 1;
}
}
(c) Paulo Santos
26
Outras rvores
rvores Splay
rvores Red-Black
rvores AA
rvores B
rvores B+
rvores B*
Etc, etc

Você também pode gostar