INE5408 Estruturas de Dados 6.3.2.Árvores Rubro- Características Algoritmos Negras
Oque são Árvores Rubro- Negras Árvores de pesquisa binária com um bit de informação adicional: a sua cor. Pode ser rubra ou Limitação da coloração dos nodos da raiz às folhas Garante que nenhum caminho é mais que duas vezes mais longo que qualquer outro Árvore semibalanceada Propriedades comuns a Árvores-B de ordem 4 negra
Histórico Árvores Red-Black foram inventadas em 1972 por Rudolf Bayer: Estudou matemática em Munique e fez doutorado também em Matemática na Universidade de Illinois, em 1966. Foi pesquisador nos Boeing Research Labs, onde inventou em 1970 a árvore-B Publicação Original: Symmetric binary B-trees: Data structures and maintenance algorithms, Acta Informatica, 1 (1972) 290-306
Propriedades Rubro- Negras Todo nodo ou é rubro ou é negro A raiz é negra Toda folha é negra Folhas são somente os nodos vazios (ponteiros nulos). Se um nodo for rubro, então ambos os filhos são negros. Para todo nodo, todos os caminhos até uma folha contém o mesmo número de nodos negros.
Implementação Rubro- Negra Nodo possui dois campos a mais: pai e cor Classe nodoRB { info : tipo_info; esq : *nodoRB; dir : *nodoRB; pai : *nodoRB; cor : {rubro, negro}; }; Folhas nulas obrigatórias (“toda folha é negra”) Pode-se empregar um único nodo sentinela para representar todas as folhas Para fins de visualização em nossos algoritmos vamos ignorar as folhas.
Ponteiro nulo representando folha negra Visualização “tradicional” 26 17 41 14 21 30 47 10 16 19 23 28 38 7 12 15 20 35 39 3 nil Ponteiro nulo representando folha negra Visualização “tradicional” 26 17 41 14 21 30 47 10 16 19 23 28 38 7 12 15 20 35 39 3
Rotações Rubro- Negras Árvores Rubro-Negras também realizam rotações para efetuar ajustes O Procedimento é quase idêntico à rotação simples das árvores AVL Mudam os nomes dos algoritmos Rotação simples à esquerda passa a se chamar rotação para a direita Rotação simples à direita passa a se chamar rotação para a esquerda
Devolvo y como a nova raiz desta subárvore Rotação para a direita RB Corresponde a uma rotação entre os nodos x e seu filho da esquerda, y, envolvendo as subárvores A, B e C Devolvo y como a nova raiz desta subárvore x A y B C
Rotação para a esquerda RB nodoRB *roda_esq(x *nodoRB) variáveis locais y, pai : *nodoRB; lado : {esq, dir}; início pai <- x->pai; //guardo o pai da subárvore que vou rodar SE pai->esq = x ENTÃO //x está pendurado de qual lado do pai? lado <- esq; SENÃO lado <- dir; FIMSE y <- x->dir; y->pai <- pai //roda & ajusta pais x->dir <- y->esq; x->dir->pai <- x; y->esq <- x; y->esq->pai <- y; SE lado = esq ENTÃO pai->esq <- y; pai->dir <- y; retorne y; fim roda_esq
Rotação para a esquerda RB nodoRB *roda_esq(x *nodoRB) variáveis locais y, pai : *nodoRB; lado : {esq, dir}; início pai <- x->pai; //guardo o pai da subárvore que vou rodar SE pai->esq = x ENTÃO //x está pendurado de qual lado do pai? lado <- esq; SENÃO lado <- dir; FIMSE y <- x->dir; y->pai <- pai //roda x->dir <- y->esq; x->dir->pai <- x; y->esq <- x; y->esq->pai <- y; SE lado = esq ENTÃO // Ajusta pais. pai->esq <- y; ENTÃO // Evita ter que passar SENÃO // pai como parâmetro. pai->dir <- y; retorne y; fim roda_esq
Rotação para a direita RB nodoRB *roda_dir(x *nodoRB) variáveis locais y, pai : *nodoRB; lado : {esq, dir}; início pai <- x->pai; //guardo o pai da subárvore que vou rodar SE pai->esq = x ENTÃO //x está pendurado de qual lado do pai? lado <- esq; SENÃO lado <- dir; FIMSE y <- x->esq; y->pai <- pai //roda & ajusta pais x->esq <- y->dir; x->esq->pai <- x; y->dir <- x; y->dir->pai <- y; SE lado = esq ENTÃO pai->esq <- y; pai->dir <- y; retorne y; fim roda_dir
Inserções Rubro- Negras A inclusão é sempre executada utilizando-se o algoritmo de inserção em árvore de busca Modificado para manter os ponteiros para o pai. Todo novo nodo é colorido rubro. Sempre ganha duas folhas nulas negras Se o pai do novo nodo for negro Está pronto, trata-se de uma árvore- Se o pai for rubro A propriedade 4 está ferida Até duas rotações devem ser realizadas RB
Ajustes Rubro- Negros Para todo nodo v definimos uma vizinhança- RB v, seu pai, seu avô e seu tio (RB é binária, haverá no máximo 1 tio) Um passo-CE de correção-ou-elevação envolve recolorir e (eventualmente) rotacionar a vizinhança-RB Um passo-CE provoca a restituição da propriedade 4 ou a elevação do erro para um nível acima na árvore-RB Para todo passo-CE existem 6 possíveis casos 3 para a direita e 3 para a esquerda RB
Relembrando: Propriedades Rubro- Negras Todo nodo ou é rubro ou é negro A raiz é negra Toda folha é negra Folhas são somente os nodos vazios (ponteiros nulos). Se um nodo for rubro, então ambos os filhos são negros. Para todo nodo, todos os caminhos até uma folha contém o mesmo número de nodos negros.
RB Caso 1e (esquerda) v possui um tio rubro e seu pai é um filho rubro da esquerda não importa se v é filho da esquerda ou direita recolorimos o pai, avô e tio de v se o bisavô de v for negro está feito caso contrário a violação de 4 foi elevada 2 níveis v é elevado dois níveis executamos um passo-CE para o novo v (avô de v)
RB Caso 1e (esquerda)
Caso 1e (inserção do 14 - esquerda) RB Caso 1e (inserção do 14 - esquerda)
Caso 2de (direita-esquerda) RB Caso 2de (direita-esquerda) v é um filho da direita, cujo pai é um filho rubro da esquerda e cujo tio é negro rotacionamos para a esquerda v e seu pai atualizamos o nodo corrente caímos no caso 3 O caso 2 (inserção) sempre é sucedido pelo caso 3 Podemos ter o caso 3 acontecendo sozinho!
Caso 2de (inserção do 15 - direita-esquerda) RB Caso 2de (inserção do 15 - direita-esquerda) E o tio negro? Folha nula é sempre negra... Rotacionamos para a esquerda. Geramos caso 3e...
RB Caso 3e (esquerda) v é um filho da esquerda, cujo pai é um filho rubro da esquerda e cujo tio é negro rotacionamos para a direita entre o avô e o pai recolorimos o pai e o avô pai fica negro avô fica rubro
RB Caso 3e
RB Caso 3e
Deleção do 32 RB É deletado como na árvore de busca não balanceada. Caso simples: basta apagar o nodo. Fizemos aqui apenas para usar a árvore resultante para ver mais exemplos de inserção. Veremos deleção mais adiante
Caso 2ed (esquerda-direita) RB Caso 2ed (esquerda-direita) v é um filho da esquerda, cujo pai é um filho rubro da direita e cujo tio é negro rotacionamos para a direita v e seu pai atualizamos o nodo corrente caímos no caso 3
Caso 2ed (inserção do 42 – esquerda-direita) RB Caso 2ed (inserção do 42 – esquerda-direita) E o tio negro? Folha nula é sempre negra... Rotacionamos para a direita. Geramos caso 3d...
RB Caso 3d (direita) v é um filho da direita, cujo pai é um filho rubro da direita e cujo tio é negro rotacionamos para a esquerda entre o avô e o pai recorimos o pai e o avô pai fica negro avô fica rubro
RB Caso 3d
RB Caso 3d
RB Inserção- RB InsereRB (nodoRB *raiz, tipoInfo info, nodoRB *nodo) nodoRB *atual, *pai, *avô; início InsereArvBusca(raiz,info,nodo); //mod.p/atualizar ref.p/pai nodo->cor <- rubro; atual <- nodo; ENQUANTO (atual ≠ raiz E atual->pai->cor = rubro) FAÇA pai <- atual->pai; avô <- pai->pai; SE avo->esq = pai ENTÃO PassoCE_esq(atual, pai, avô); SENÃO PassoCE_dir(atual, pai, avô); FIMSE FIM ENQUANTO raiz->cor <- negro; //caso zero, por via das dúvidas fim.
RB RB Passo-CE- PassoCE_esq (nodoRB *atual, *pai, *avô) nodoRB *tio; início tio <- avô->dir; SE tio->cor = rubro ENTÃO //caso 1 pai->cor <- negro; avô->cor <- rubro; tio->cor <- negro; atual <- avô; //sobe 2 níveis SENÃO SE pai->dir = atual ENTÃO //caso 2 roda_esq(pai); atual <- atual->esq; //reseta atual FIMSE pai->cor <- negro; //caso3 roda_dir(avô); fim PassoCE-esq
RB RB Passo-CE- PassoCE_dir (nodoRB *atual, *pai, *avô) nodoRB *tio; início tio <- avô->esq; SE tio->cor = rubro ENTÃO //caso 1 pai->cor <- negro; avô->cor <- rubro; tio->cor <- negro; atual <- avô; //sobe 2 níveis SENÃO SE pai->esq = atual ENTÃO //caso 2 roda_dir(pai); atual <- atual->dir; //reseta atual FIMSE pai->cor <- negro; //caso3 roda_esq(avô); fim PassoCE-dir
Negras Deleções Rubro- RB Negras Deleções Rubro- Deleção do nodo v é executada utilizando-se o algoritmo de deleção em árvore de busca Modificado para manter os ponteiros para o pai Subimos w, o predecessor inordem de v Maior elemento da subárvore esquerda Na falta: menor elemento da subárvore direita Ao subir w nunca subimos junto a cor de w o nodo cujo valor foi “retirado” mantém a cor original, associada à chave v
RB Negras Deleções Rubro- Ex.: deleção do 17: v w
16 copia para v. Com w faço o quê? RB Negras Deleções Rubro- O problema em RB será sempre tratar w: v 16 copia para v. Com w faço o quê? w
Negras Deleções Rubro- 10 Casos: Caso 0 Casos 1 a 4 para: rubro e RB Negras Deleções Rubro- 10 Casos: Caso 0 rubro e negro Casos 1 a 4 para: (e) filhos da esquerda (d) filhos da direita
Negras Deleções Rubro- Caso 0.R: Caso 0. : N RB Negras Deleções Rubro- Caso 0.R: Se w for rubro, a árvore-RB continua válida Caso 0. : Se w for negro e possuir um filho rubro N → recolorimos
9 copia para v. Nodo rubro é simplesmente eliminado. RB Negras Deleções Rubro- Caso 0.R: deleção do 8 v w 9 copia para v. Nodo rubro é simplesmente eliminado.
Árvore RB resultante é equilibrada. Negras Deleções Rubro- Caso 0.R: deleção do 8 Árvore RB resultante é equilibrada.
11 copia para w. Nodo rubro é eliminado. RB Negras Deleções Rubro- Caso 0. : deleção do 13 N v w 12 copia para v. 11 copia para w. Nodo rubro é eliminado.
11 copia para w. Nodo rubro é eliminado. RB Negras Deleções Rubro- Caso 0. : deleção do 13 N OK! w 12 copia para v. 11 copia para w. Nodo rubro é eliminado.
RB Negras Deleções Rubro- Caso 0. : deleção do 13 N 11 muda de cor
RB Negras Deleções Rubro- Caso 0. : deleção do 13 N FEITO!
Negras Deleções Rubro- RB Negras Deleções Rubro- Problema ocorre quando w e seus filhos são todos negros deleção de w fere propriedade 5 haverá um caminho com um nodo negro a menos Realizaremos recolorações e rotações para restaurar propriedades-RB vizinhança-RB consistirá do nodo atual, seu pai, seu irmão e os sobrinhos (filhos do irmão) recoloração e rotação ou restituirão a propriedade 5 ou elevarão a violação 1 nível na árvore: passo-CED (correção-ou-elevação-em- deleção) Para todo passo-CED haverá 8 casos 4 para a esquerda e 4 para a direita
Deleções Rubro- (esquerda) RB Deleções Rubro- (esquerda) Negras Caso 1 - Irmão y de w é rubro Rotação transforma-o no caso 2, 3 ou 4 Casos 2, 3 e 4: irmão y de w é negro Distingüem-se dependendo dos filhos de y Caso 2 - ambos os filhos de y são negros Recolorimos (violação pode ser elevada um nível) Caso 3 - y->esq é rubro e y->dir é negro Recolorimos e rodamos É transformado no caso 4 Caso 4 - y->dir é rubro Ajuste termina aqui
Deleções Rubro- (esquerda) RB Deleções Rubro- (esquerda) Negras Caso 1 - Irmão y de w é rubro Rotação transforma-o no caso 2, 3 ou 4 Ex.: Deleção do 16 v y w
Deleções Rubro- (esquerda) RB Deleções Rubro- (esquerda) Negras Caso 1 - Irmão y de w é rubro Rotação transforma-o no caso 2, 3 ou 4 Ex.: Deleção do 16 v vizinhança-RB y w
Deleções Rubro- (esquerda) RB Deleções Rubro- (esquerda) Negras Caso 1 - Irmão y de w é rubro Rotação transforma-o no caso 2, 3 ou 4 Sobe 11 v y w
Deleções Rubro- (esquerda) RB Deleções Rubro- (esquerda) Negras Caso 1 - Irmão y de w é rubro Rotação transforma-o no caso 2, 3 ou 4 Rotacionamos para esquerda y w
Deleções Rubro- (esquerda) RB Deleções Rubro- (esquerda) Negras Caso 1 - Irmão y de w é rubro Rotação transforma-o no caso 2, 3 ou 4 Recolorimos (como parte da rotação) y w
Resumo: deleção - Caso 1e (esquerda) RB Resumo: deleção - Caso 1e (esquerda) Se Irmão y de w é rubro rotacione para a esquerda entre pai e y troque cor de pai e y
Deleções Rubro- (esquerda) RB Deleções Rubro- (esquerda) Negras Caso 2 - ambos os filhos de y são negros Recolorimos (violação pode ser elevada 1 nível) w y
Deleções Rubro- (esquerda) RB Deleções Rubro- (esquerda) Negras Caso 2 - ambos os filhos de y são negros Recolorimos (violação pode ser elevada de nível) w y vizinhança-RB
Deleções Rubro- (esquerda) RB Deleções Rubro- (esquerda) Negras Caso 2 - ambos os filhos de y são negros Recolorimos (violação pode ser elevada 1 nível)
Deleções Rubro- (esquerda) RB Deleções Rubro- (esquerda) Negras Caso 2 - ambos os filhos de y são negros Recolorimos (violação pode ser elevada 1 nível)
Resumo: deleção - Caso 2e (esquerda) RB Resumo: deleção - Caso 2e (esquerda) Se filhos de y são ambos negros troque cor de y para rubro mova w um nível acima
Deleções Rubro- (esquerda) RB Deleções Rubro- (esquerda) Negras Caso 3 – sobrinho y->esq é rubro (sobrinho próximo) e y->dir é negro Recolorimos e rodamos É transformado no caso 4 Ex.: Deleção do 28 v y w
Deleções Rubro- (esquerda) RB Deleções Rubro- (esquerda) Negras Caso 3 – sobrinho y->esq é rubro e y->dir é negro Recolorimos e rodamos É transformado no caso 4 Subimos 25 e preparamos para rodar v y w
Deleções Rubro- (esquerda) RB Deleções Rubro- (esquerda) Negras Caso 3 – sobrinho y->esq é rubro e y->dir é negro Rodamos e recolorimos É transformado no caso 4 Rotacionamos v y w
Deleções Rubro- (esquerda) RB Deleções Rubro- (esquerda) Negras Caso 3 – sobrinho y->esq é rubro e y->dir é negro Rodamos e recolorimos É transformado no caso 4 Recolorimos v y w
Deleções Rubro- (esquerda) RB Deleções Rubro- (esquerda) Negras Caso 3 – sobrinho y->esq é rubro e y->dir é negro Rodamos e recolorimos É transformado no caso 4 Transformou-se no caso 4 v y w
Resumo: deleção - Caso 3e (esquerda) RB Resumo: deleção - Caso 3e (esquerda) y->esq é rubro e y->dir é negro troque cor de y para rubro e de y->esq para negro rotacione para direita entre y e y->esq
O caso 3 (deleção) sempre é sucedido pelo caso 4 Podemos ter o caso 4 acontecendo sozinho!
Deleções Rubro- (esquerda) RB Deleções Rubro- (esquerda) Negras Caso 4 - y->dir é rubro (sobrinho distante) Recolorimos e rodamos Ajuste termina aqui v y w
Deleções Rubro- (esquerda) RB Deleções Rubro- (esquerda) Negras Caso 4 - y->dir é rubro (sobrinho distante) Rodamos e recolorimos Ajuste termina aqui v y w
Deleções Rubro- (esquerda) RB Deleções Rubro- (esquerda) Negras Caso 4 - y->dir é rubro (sobrinho distante) Rodamos e recolorimos Ajuste termina aqui
Deleções Rubro- (esquerda) RB Deleções Rubro- (esquerda) Negras Caso 4 - y->dir é rubro (sobrinho distante) Rodamos e recolorimos Ajuste termina aqui
Resumo: deleção - Caso 4e (esquerda) RB Resumo: deleção - Caso 4e (esquerda) y->dir (sobrinho distante) é rubro nodos c1 e c2 podem ser rubros ou negros e não mudam mude cor de y->dir e de pai para negro mude cor de y para c1->cor rotacione para a esquerda entre pai e y faça a raiz da árvore ser w condição de término
Deleção - Caso 4e (esquerda) RB Deleção - Caso 4e (esquerda)
Correção-ou-elevação- (deleção) alto nível RB nodoRB *passoCED(nodoRB *w, *raiz) início ENQUANTO w ≠ raiz FAÇA // Cond. de término SE w = w->pai->esq ENTÃO w ← passoCED_esq(w, raiz); // Esquerda SENÃO w ← passoCED_dir(w, raiz); // Direita FIM ENQUANTO retorne w; FIM passoCED Observe que aqui não foi contemplada uma rotina de alto nível que deleta e sobe w, onde são tratadas as duas situações (Caso 0) onde um passo- CED é desnecessário e que invoca passoCED(). Esta fica por conta do aluno. RB
RB nodoRB *passoCED_esq(nodoRB *w, *raiz) variáveis nodoRB *y; início y ← w->pai->dir; // Irmão da direita SE y->cor = RUBRO ENTÃO y->cor ← NEGRO; // Caso 1 w->pai->cor ← RUBRO; // Caso 1 roda_esq(w->pai); // Caso 1 y ← w->pai->direita; // Reseta Caso 1 FIMSE SE y->esq->cor = NEGRO E y->dir->cor = NEGRO ENTÃO y->cor ← RUBRO; // Caso 2 w ← w->pai; // Sobe Caso 2 SENÃO SE y->dir->cor = NEGRO ENTÃO y->esq->cor ← NEGRO; // Caso 3 y->cor ← RUBRO; // Caso 3 roda_dir(y); // Caso 3 y ← w->pai->dir; // Caso 3 y->cor ← w->pai->cor; // Caso 4 w->pai-cor ← NEGRO; // Caso 4 y->dir->cor ← NEGRO; // Caso 4 roda_esq(w->pai); // Caso 4 w ← raiz; // Caso 4 FIMSE FIMSE retorne w; FIM passoCED_esq
Trabalho Implemente uma classe ÁrvoreRB com todas as operações vistas Implementação no VPL Implemente a árvore usando Templates Fornecidos Implemente a árvore com um número de elementos variável definido na instanciação Use as melhores práticas de orientação a objetos Documente todas as classes, métodos e atributos. Aplique os testes unitários disponíveis no Moodle da disciplina para validar sua estrutura de dados.