Algoritmos e Estruturas de Dados 00/006 Árvore BB: árvore Vermelho-Preto cada nó tem no máximo 1 filho vermelho Árvore AA ; semelhante a árvore BB, mas: só filhos direitos podem ser vermelhos reduz casos de equilíbrio a remoção é um processo mais simples; filho único de um nó interno é vermelho: informação do nó a apagar é substituída pela menor subárvore direita em vez da cor, o nó guarda informação do nível nível = 1, em nó folha nível = nível do pai, em nó vermelho nível = nível do pai 1, em nó preto 1
Propriedades: filho esquerdo tem nível 1 unidade abaixo do pai filho direito tem nível igual ou uma unidade abaixo do pai ligação ao filho direito pode ser horizontal 1 0 8 3 40 6 80 90 Desequilíbrio da árvore pode ser originado por: ligação horizontal à esquerda (ex: inserção do valor ) ligação horizontal à direita (ex: inserção do valor 4) 3 Desequilíbrio por ligação horizontal à esquerda resolução: rotação à direita (skew) X P rotação à direita X P A B C A B C Desequilíbrio por ligação horizontal à direita resolução: rotação à esquerda (split) X R G C rotação à esquerda X R G A B C A B 4
Declaração da classe AANode template <class Comparable> class AANode Comparable element; AANode *left, *right; int level; AANode() : left(null), right(null), level(1) ; AANode(const Comparable & e, AANode *lt, AANode *rt, int lv =1) : element(e), left(lt), right(rt), level(lv) ; ; friend class AATree<Comparable>; Declaração da classe AATree e construtor template <class Comparable> class AATree AANode<Comparable> *root; const Comparable ITEM_NOT_FOUND; AANode<Comparable> *nonulo; //... ; template <class Comparable> AATree<Comparable>:: AATree(const Comparable & notfound ) : ITEM_NOT_FOUND(notFound) nonulo = new AANode<Comparable>; nonulo->left = nonulo->right = nonulo; nonulo->level = 0; root = nonulo; 6 3
classe AATree : skew e split template <class Comparable> void AATree<Comparable>::skew(AANode<Comparable> * & t) const if ( t->left->level == t->level ) rotatewithleftchild(t); template <class Comparable> void AATree<Comparable>::split(AANode<Comparable> * & t) const if ( t->right->right->level == t->level ) rotatewithrightchild(t); t->level++; 7 Inserção de um novo elemento x na árvore de raiz t se t.left.level == t.level rotação com filho esquerdo : skew se t.right.right.level == t.level rotação com filho direito : split template <class Comparable> void AATree<Comparable>:: insert(const Comparable & x, AANode<Comparable> * & t) if ( t == nonulo ) t = new AANode<Comparable>(x, nonulo, nonulo); else if ( x < t->element ) insert(x, t->left); else if ( t->element < x ) insert(x, t->right); else return; // nó repetido skew(t); split(t); 8 4
: inserção de elementos inserir 4 1 0 8 3 40 4 6 80 90 após split em 3 1 40 0 8 3 4 6 80 90 após skew em 0 1 40 0 8 3 4 6 80 90 9 : inserção de elementos após split em 40 1 40 0 8 3 4 6 80 90 após skew em e split em 0 1 40 8 3 4 6 80 90 árvore aumentou 1 nível 10
Eliminação de um elemento Nó a eliminar ou é folha, ou tem filho direito substituir pelo menor elemento da subárvore direita, que está no nível 1 procedimento a adoptar: para remover, descer na árvore mantendo registo do nó a apagar e do valor mínimo Ao chegar ao fundo da árvore, substituir o nó a eliminar pelo mínimo, e remover mínimo Ajustar nós e seus níveis, e reequilibrar a árvore se necessário 1 3 4 6 7 Se eliminar nó 1: todos os nós passam a nível 1, introduzindo ligações horizontais à esquerda. 3 chamadas a skew + chamadas a split 11 template <class Comparable> void AATree<Comparable>:: remove(const Comparable & x, AANode<Comparable> * & t) static AANode<Comparable> *lastnode, *deletednode = nonulo; if ( t!= nonulo ) // percorre árvore, instanciando deletednode e lastnode // deletednode: nó a eliminar ; lastnode: nó com valor a substituir lastnode = t; if ( x < t->element ) remove(x, t->left); else deletednode = t; remove(x, t->right); // continua... 1 6
// se fundo da árvore e x está presente, remover if ( t == lastnode ) if ( deletednode == nonulo x!= deletednode->element ) return; // elemento não existe deletednode->element = t->element; deletednode = nonulo; t = t->right; delete lastnode; else // não estamos no fundo da árvore: reequilibrar if ( ( t->left->level < t->level -1 ) ( t->right->level < t->level -1 ) ) if ( t->right->level > --t->level ) t->right->level = t->level; skew(t); skew(t->right); skew(t->right->right); split(t); split(t->right); 13 Eliminar elemento 1 1 3 4 6 7 árvore resultante: (como?) 3 4 6 7 14 7
Treaps Árvore binária de pesquisa ideia é usar aleatoriedade para tentar balancear árvores binárias de pesquisa nó da árvore: 1 elemento, apontadores para filhos, e uma prioridade geralmente, prioridades são determinadas aleatoriamente prioridade de um nó é sempre não inferior à do seu pai (como no heap de mínimo) eficiência esperada: O(log N) Inserção de um elemento inserir como folha rodar para cima até satisfazer prioridades Eliminação de um elemento procurar elemento, passar prioridade a infinito rodar para baixo com filho de menor prioridade, até ser folha, e apagar 1 Treaps Declaração da classe Treap template <class Comparable> class Treap TreapNode<Comparable> *root; const Comparable ITEM_NOT_FOUND; TreapNode<Comparable> *nonulo; public: explicit Treap(const Comparable & notf) ; Treap(const Treap & rhs); ; template <class Comparable> Treap<Comparable>::Treap(const Comparable & notf) : ITEM_NOT_FOUND(notF) nonulo = new TreapNode<Comparable>; nonulo->left = nonulo->right = nonulo; nonulo->priority = INT_MAX; root = nonulo; 16 8
Treaps classe Treap : inserção de um elemento template <class Comparable> void Treap<Comparable>:: insert(const Comparable & x, TreapNode<Comparable> * & t) if ( t == nonulo ) t = new TreapNode<Comparable>( x, nonulo, nonulo, rand() ); else if ( x < t->element ) insert(x, t->left); if ( t->left->priority < t->priority ) rotatewithleftchild(t); else if (t->element < x ) insert(x, t->right); if ( t->right->priority < t->priority ) rotatewithrightchild(t); 17 Treaps classe Treap : eliminação de um elemento template <class Comparable> void Treap<Comparable>:: remove(const Comparable & x, TreapNode<Comparable> * & t) if ( t!= nonulo ) if ( x < t->element ) remove(x, t->left); else if (t->element < x ) remove(x, t->right); else // encontrou elemento if ( t->left->priority < t->right->priority ) rotatewithleftchild(t); else rotatewithrightchild(t); if ( t!= nonulo ) remove(x,t); else delete (t->left); t->left = nonulo; 18 9