Universidade Federal de Mato Grosso Estrutura de Dados II Curso de Ciência da Computação Prof. Thiago P. da Silva [email protected] Agenda Definições Fator de Balanceamento Estrutura de um Nó Operações Inserção Remoção Busca Rotações Rotação á esquerda Rotação á direita Rotação dupla á esquerda Rotação dupla á direita Árvore Binária - Definição Grafo acíclico, conexo, dirigido e que cada nó não tem grau maior que dois Não existe mais do que um caminho entre dois nós distintos Uma árvore binária é uma estrutura de dados caracterizada por: Ou não tem elemento algum (árvore vazia) Ou tem um elemento distinto, denominado raiz, com dois ponteiros para duas estruturas diferentes, denominadas subárvore esquerda (sae) e subárvore direita (sad) Árvore Binária - Definição Definições: PROFUNDIDADE - distância de um nó até a raiz NÍVEL – conjunto de nós com a mesma profundidade ALTURA – maior profundidade da árvore NÓS - são todos os itens guardados na árvore RAIZ - é o nó do topo da árvore FILHOS - são os nós que vem depois dos outros nós PAIS - são os nós que vem antes dos nós filhos FOLHAS - são os nós que não têm filhos; são os últimos nós da árvore Árvore AVL - Definição Uma árvore AVL é uma árvore balanceada cuja diferença em altura entre a subárvore esquerda (SAE) e a subárvore direita (SAD) (em qualquer nó) deve ser, no máximo, de um nível. Numa árvore AVL, cada chave é única e as operações de inserção/ remoção tentam manter o equilíbrıo da árvore. Definição: Uma árvore binária vazia é sempre balanceada por altura. Se T não é vazia e Tesq e Tdir são sub-árvores da esquerda e direita, então T é balanceada por altura se: 1. Tesq e Tdir são balanceadas por altura; 2. He-Hd = ±1, sendo Hd e He a altura de Tesq e Tdir, respectivamente. Árvore AVL - Definição Em cada nó, existe um campo adicional que indica a situação de equilíbrio desse nó, chamado de fator de balanceamento (FB): 0 : equilibrada; 1 : sub-árvore esquerda tem mais um nível que a da direita; -1 : sub-árvore direita tem mais um nível que a da esquerda Árvore AVL – Estrutura de um Nó Novos atributos: FB: armazena o fator de balanceamento daquele nó dentro da árvore AVL. Pai: guarda a referência para o nó pai. No caso da raiz da árvore, o pai é igual a null. typedef struct no_AVL AVL; struct no_AVL { int info; int fb; // fator de balanceamento AVL *pai; AVL *esq; AVL *dir; }; Árvore AVL – Calculando a Altura de um Nó int altura(Arvore t) { int altE, altD: AVL *q, *temp; if (t == NULL) return -1; else { altE = altura(t->esq); altD = altura(t->dir); if (altE < altD) return altD + 1; else return altE + 1; } } Árvore AVL – Operações Inserção Inserção em uma árvore AVL deve ser dada pela inserção do nodo seguida de uma verificação na propriedade do fator de balanceamento. Caso não obedeça a essa propriedade, deve-se fazer uma rotação conveniente. Remoção A remoção deve ser dada por uma rotação em torno do nó a ser removido, a fim de torná-lo folha para que então possa ser removido. Em alguns casos, após a remoção são necessárias rotações para ajustar o fator de balanceamento. Pesquisa O número de comparações para localizar um elemento em AVL é aproximadamente 1.44 log2 n no pior caso. Árvore AVL – Operações Inserção e remoção são operações que podem desbalancear a árvore AVL. Considere uma árvore T qualquer com raiz r e subárvores esquerda E e direita D, e supondo que a inserção deve ser feita na subárvore da esquerda. Podemos distriguir 3 casos: 1. Se He = Hr, então E e D ficam com alturas diferentes mas continuam balanceadas. 2. Se He < Hd, então E e D ficam com alturas iguais e balanceamento foi melhorado. 3. Se He > Hd, então E fica ainda maior e balanceamento foi violado. Árvore AVL – Operações Exemplo: Nós 9 ou 11 podem ser inseridos sem balanaceamento. Subárvore com raiz 10 passa a ter uma subárvore e subárvore com raiz 8 vai ficar melhor balanceada! Inserção dos nós 3, 5 ou 7 requerem que a árvore seja rebalanceada! Árvore AVL – Inserção na árvore Para inserir um nó X em uma árvore AVL, basta seguirmos os seguintes passos (top-down): (1) Inserir X na árvore AVL usando o mesmo algoritmo de inserção de um nó em uma árvore de busca binária. Recursivamente, empilhar cada nó que é visitado a partir do nó raiz até X, exceto o próprio X; (2) Verificar se a pilha está vazia: Se sim, o algoritmo termina. Senão, vá para o passo (3). (3) Desempilhar um nó e verificar se a diferença de altura entre a subárvore da esquerda e da direita desse nó é maior que 1. Se sim, vá para o passo (2). Senão, você precisará rotacionar os nós. Depois de realizada a rotação, o algoritmo termina. Árvore AVL – Inserção na árvore Alternativamente, você pode manter um ponteiro na estrutura nó para o seu pai. (No* pai) Desta forma, é possível ”caminhar” de baixo para cima na árvore. O algoritmo para na raiz, pois pai==null: (1) Inserir X na árvore AVL. Recursivamente, empilhar cada nó que é visitado a partir do nó até X a raiz, exceto a própria raiz; (2) Verificar se a pilha está vazia: Se sim, o algoritmo termina. Senão, vá para o passo (3). (3) Desempilhar um nó e verificar se a diferença de altura entre a subárvore da esquerda e da direita desse nó é maior que 1. Se sim, vá para o passo (2). Senão, você precisará rotacionar os nós. Depois de Árvore AVL – Inserção na árvore Exemplos: 10, 20, 30 30, 20, 10 Façam o desenho destas árvores! Árvore AVL – Inserção na árvore Exemplos: 10, 20, 30 30, 20, 10 Observações: Quando os sinais dos fatores de balanceamento dos antecessores forem iguais, então a rotação é simples Se forem negativos (-), então será uma rotação à esquerda Se forem positivo (+), então será uma rotação à direita Árvore AVL – Rotações Rotação à esquerda ”Empurrar o nó para baixo e para esquerda. O filho à direita do nó o substitui, e o filho à esquerda do filho à direita vem a ser o novo filho à direita do nó”. Seja Y o filho à direita de X Torne o filho à esquerda de Y o filho à direita de X. Torne X filho à esquerda de Y void rotacao_esquerda(AVL *p) { AVL *y, *temp; y = p->dir; temp = y->esq; y->esq = p; p->dir = temp; } Árvore AVL – Rotações Rotação simples à esquerda: 10, 20, 30 Seja Y o filho à direita de X Torne o filho à esquerda de Y o filho à direita de X. ●Torne X filho à esquerda de Y ● ● 10 20 20 10 30 30 Árvore AVL – Rotações Rotação simples à esquerda: 10, 20, 30 Seja Y o filho à direita de X Torne o filho à esquerda de Y o filho à direita de X. ●Torne X filho à esquerda de Y ● ● FB=-2 10 20 FB=-1 20 FB=0 30 10 30 Árvore AVL – Rotações Rotação simples à esquerda: 10, 20, 30 Seja Y o filho à direita de X Torne o filho à esquerda de Y o filho à direita de X. ●Torne X filho à esquerda de Y ● ● FB=-2 10 X FB=-2 FB=-1 20 Y 10 FB=0 FEX 20 30 FEY FEX – Filho a esquerda de X FEY – Filho à esquerda de Y FB=-1 Y 30 Árvore AVL – Rotações Rotação simples à esquerda: 10, 20, 30 Seja Y o filho à direita de X ●Torne o filho à esquerda de Y o filho à direita de X. ●Torne X filho à esquerda de Y ● FB=-2 10 X FB=-2 FB=-1 20 Y 10 FB=0 30 FEX – Filho a esquerda de X FEY – Filho à esquerda de Y FEX FB=-1 20 FEY Y 30 Árvore AVL – Rotações Rotação simples à esquerda: 10, 20, 30 Seja Y o filho à direita de X ●Torne o filho à esquerda de Y o filho à direita de X. ●Torne X filho à esquerda de Y ● FB=-2 10 X FB=-2 FB=-1 20 Y 10 FB=0 FEX 20 30 FEY FEX – Filho a esquerda de X FEY – Filho à esquerda de Y FB=-1 Y 30 Árvore AVL – Rotações Rotação simples à esquerda: 10, 20, 30 Seja Y o filho à direita de X ●Torne o filho à esquerda de Y o filho à direita de X. ●Torne X filho à esquerda de Y ● FB=-2 10 X FB=-1 20 Y FB=0 20 FB=0 FB=0 30 Y 10 FEX – Filho a esquerda de X FEY – Filho à esquerda de Y FEX FEY FB=0 30 Árvore AVL – Rotações Rotação à direita ”Empurrar o nó para baixo e para a direita. O filho à esquerda do nó o substitui, e o filho à direita do filho à esquerda vem a ser o novo filho à esquerda do nó. Seja Y o filho à esquerda de X Torne o filho à direita de Y o filho à esquerda de X. Torne X o filho à direita de Y void rotacao_direita(AVL *p) { AVL *q, *temp; q = p->esq; temp = q->dir; q->dir = p; p->esq = temp; } Árvore AVL – Rotações Rotação simples à direita: 30, 20, 10 Seja Y o filho à esquerda de X Torne o filho à direita de Y o filho à esquerda de X. ●Torne X o filho à direita de Y ● ● 30 20 10 20 10 30 Árvore AVL – Rotações Exemplo 1: Inserção do elemento 16 na árvore 10 15 6 3 2 7 4 17 Árvore AVL – Rotações Exemplo 1: Inserção do elemento 16 na árvore FB=1 10 FB=1 FB=-1 15 6 FB=0 FB=0 3 FB=0 2 7 FB=0 4 FB=0 17 Árvore AVL – Rotações Exemplo 1: Inserção do elemento 16 na árvore FB=0 10 FB=1 FB=-2 15 6 FB=0 3 FB=0 2 FB=1 FB=0 17 7 FB=0 4 FB=0 16 Árvore AVL – Rotações Exemplo 1: Inserção do elemento 16 na árvore FB=0 10 FB=1 FB=-2 15 6 FB=0 FB=0 3 FB=0 2 Y 17 7 FB=0 4 FB=1 FB=0 16 Árvore AVL – Rotações Exemplo 1: Inserção do elemento 16 na árvore FB=0 10 FB=1 FB=0 15 6 FB=0 FB=0 3 FB=0 2 7 FB=0 4 16 FB=0 Y FB=0 17 Árvore AVL – Rotações Exemplo 2: Inserção do elemento 1 na árvore Árvore AVL – Rotações Exemplo 2: Inserção do elemento 1 na árvore 10 15 6 3 2 1 7 4 17 Árvore AVL – Rotações Exemplo 2: Inserção do elemento 1 na árvore 10 15 6 3 2 1 7 4 17 Árvore AVL – Rotações Exemplo 2: Inserção do elemento 1 na árvore 10 15 3 2 1 17 6 4 7 Árvore AVL – Rotações E para os casos em que os sinais dos fatores de balanceamento dos antecessores forem diferentes? Exemplo: 10, 30, 20 10 30 20 Árvore AVL – Rotações E para os casos em que os sinais dos fatores de balanceamento dos antecessores forem diferentes? Exemplo: 10, 30, 20 10 30 20 Aplicamos rotações duplas Árvore AVL – Rotações Rotação dupla à esquerda Rotação simples à direita Rotação simples à esquerda void rotacao_dupla_esquerda(AVL *p) { rotacao_direita(p->dir); rotacao_esquerda(p); } Árvore AVL – Rotações Rotação dupla à esquerda Exemplo: 20 10 10 30 20 10, 30, 20 10 20 30 30 Árvore AVL – Rotações Rotação dupla à esquerda Exemplo: 10, 30, 20 Rotação simples à direita Rotação simples à esquerda 20 10 10 30 20 10 20 30 30 Árvore AVL – Remoção Como proceder: 1 - Faça a remoção como na árvore binária de busca 2 – Percorrer o caminho desde o pai do nó removido até a raiz da árvore, verificando os fatores de balanceamento e fazendoas rotações apropriadas Pode ser necessária mais do que uma rotação Árvore AVL – Rotações Exemplo 1: Remoção do elemento 7 na árvore 10 17 5 3 4 13 12 19 15 7 16 20 Árvore AVL – Rotações Exemplo 1: Remoção do elemento 7 na árvore 10 17 5 3 4 13 12 19 15 7 16 20 Árvore AVL – Rotações Exemplo 1: Remoção do elemento 7 na árvore 10 17 5 19 15 3 4 13 12 16 20 Árvore AVL – Rotações Exemplo 1: Remoção do elemento 7 na árvore 10 5 17 19 15 3 4 13 12 16 20 Árvore AVL – Rotações Exemplo 1: Remoção do elemento 7 na árvore 10 4 3 17 13 12 19 15 5 16 20 Árvore AVL – Rotações Exemplo 1: Remoção do elemento 7 na árvore 10 4 3 17 13 12 19 15 5 16 20 Árvore AVL – Rotações Exemplo 1: Remoção do elemento 7 na árvore 15 10 17 4 3 13 5 12 16 19 20