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