Árvore vermelha preta sobre árvore AVL


108

As árvores AVL e Red black são auto-equilibradas, exceto as cores vermelha e preta nos nós. Qual é a principal razão para escolher Red black trees em vez de árvores AVL? Quais são as aplicações de Red black trees?



1
Como um aparte, os desenvolvedores do Rust escolheram usar uma árvore B em vez de qualquer uma delas para seu mapa ordenado padrão.
Tom Anderson de

Respostas:


123

Qual é a principal razão para escolher Red black trees em vez de árvores AVL?

As árvores red-black e as árvores AVL são as árvores de pesquisa binárias balanceadas mais comumente usadas e oferecem suporte para inserção, exclusão e consulta garantida O(logN) time. No entanto, existem os seguintes pontos de comparação entre os dois:

  • As árvores AVL são mais rigidamente balanceadas e, portanto, fornecem pesquisas mais rápidas. Portanto, para uma tarefa de pesquisa intensiva, use uma árvore AVL.
  • Para tarefas intensivas de inserção, use uma árvore Red-Black.
  • As árvores AVL armazenam o fator de equilíbrio em cada nó. Isso ocupa O(N)espaço extra. Porém, se sabemos que as chaves que serão inseridas na árvore sempre serão maiores que zero, podemos usar o bit de sinal das chaves para armazenar as informações de cor de uma árvore vermelho-preto. Assim, em tais casos, a árvore vermelho-preto não ocupa espaço extra.

Quais são as aplicações de Red black tree?

Árvores vermelho-pretas são de uso mais geral. Eles se saem relativamente bem em adicionar, remover e pesquisar, mas as árvores AVL têm pesquisas mais rápidas ao custo de adicionar / remover mais lentamente. A árvore vermelho-preto é usada no seguinte:

  • Java: java.util.TreeMap,java.util.TreeSet
  • C ++ STL (na maioria das implementações): map, multimap, multiset
  • Kernel do Linux: planejador completamente justo, linux / rbtree.h

43
In general, the rotations for an AVL tree are harder to implement and debug than that for a Red-Black tree.não é verdade.
Jingguo Yao

9
Para ser pedante, o padrão C ++ não exige isso std:: mape amigos usam qualquer estrutura particular. Isso é deixado para a implementação, embora libstdc ++ e Dinkumware pelo menos usem árvores vermelhas e pretas, e parece que você está certo na prática.
mbozzi

25
O fator de equilíbrio armazenado em cada nó de uma árvore AVL é de dois bits (-1 / 0 / +1). Uma árvore vermelho-preto armazena um bit de informação de cor em cada nó. Portanto, no total, ambas as árvores requerem memória O (N) para as informações extras.
Seppo Enarvi

5
"Para tarefas intensivas de inserção, use uma árvore Red-Black." Por quê? A inserção da árvore AVL leva apenas uma rotação na pior das hipóteses, enquanto a árvore Red Black pode levar duas.
Daniel

3
Isto deve ser atualizado de acordo com a análise de Ben Pfaff de 2003 sobre o desempenho do BST - árvores AVL são de uso mais geral e têm melhor desempenho. Seria interessante rastrear razões históricas exatas para Java, C ++ e o kernel do Linux escolherem a implementação mais lenta.
David McManamon

16

Tente ler isto artigo

Ele oferece alguns bons insights sobre diferenças, semelhanças, desempenho, etc.

Aqui está uma citação do artigo:

Árvores RB são, assim como árvores AVL, auto-equilibrantes. Ambos fornecem desempenho de inserção e pesquisa O (log n).

A diferença é que as RB-Trees garantem O (1) rotações por operação de pastilha. Isso é o que realmente custa o desempenho em implementações reais.

Simplificadas, as RB-Trees ganham essa vantagem por serem conceitualmente 2-3 árvores sem carregar a sobrecarga de estruturas de nós dinâmicas. Fisicamente, as árvores RB são implementadas como árvores binárias, as bandeiras vermelhas / pretas simulam 2-3 comportamento

Pelo que entendi, as árvores AVL e as árvores RB não estão muito distantes em termos de desempenho. Uma árvore RB é simplesmente uma variante de uma árvore B e o balanceamento é implementado de forma diferente de uma árvore AVL.


1
AFIAK, uma árvore AVL também tem rotação O (1) por inserção. Para árvore RB e AVL - uma inserção pode ter 1 ou 0 rotações. Se a rotação acontecer, os algoritmos param. Se isso não acontecer, normalmente, os algoritmos continuam a verificar / redesenhar os nós da base até a raiz da árvore. Portanto, às vezes a rotação O (1) pode ser melhor porque elimina a varredura dos itens restantes O (log (n)). Como a árvore AVL, em média, faz mais rotação, a árvore AVL tem, geralmente, melhor equilíbrio ~ 1,44 log (N) do que a árvore RB 2 log (N).
Sergey Shandar

4

Nossa compreensão das diferenças de desempenho melhorou ao longo dos anos e agora o principal motivo para usar árvores vermelhas e pretas sobre AVL seria não ter acesso a uma boa implementação de AVL, uma vez que são um pouco menos comuns, talvez porque não são cobertos pelo CLRS.

Ambas as árvores são agora consideradas formas de árvores equilibradas, mas as vermelho-pretas são consistentemente mais lentas em cerca de 20% nos testes do mundo real . Ou até 30-40% mais lento quando os dados sequenciais são inseridos .

Portanto, as pessoas que estudaram árvores vermelho-pretas, mas não árvores AVL, tendem a escolher árvores vermelho-pretas. Os principais usos para árvores vermelho-pretas são detalhados na entrada da Wikipedia para eles .


1
Engraçado! na minha leitura, o artigo da libavl parece dizer que AVL e RB estão frente a frente, e nenhum é claramente melhor que o outro em geral (qual é o melhor depende da carga de trabalho). Não vejo nenhuma afirmação de que o AVL seja 20% mais rápido em geral.
Stefan

3

Outras respostas aqui resumem bem os prós e contras das árvores RB e AVL, mas achei essa diferença particularmente interessante:

Árvores AVL não suportam custo de atualização amortizado constante [mas árvores vermelhas e pretas sim]

Fonte: Mehlhorn & Sanders (2008) (seção 7.4)

Assim, enquanto ambas as árvores RB e AVL garantem O (log (N)) tempo de pior caso para pesquisa, inserção e exclusão, restaurar a propriedade AVL / RB após inserir ou excluir um nó pode ser feito em O (1) tempo amortizado para árvores vermelho-pretas.


Eu acredito que a inserção da árvore AVL tem o mesmo custo amortizado / similar, mas produz uma árvore melhor balanceada (1,44 log (N) vs 2log (N)). Ao mesmo tempo, a exclusão na árvore AVL pode exigir mais rotações. IMHO, isso é tratado em WAVL en.wikipedia.org/wiki/WAVL_tree
Sergey Shandar

1

Os programadores geralmente não gostam de alocar memória dinamicamente. O problema com a árvore avl é que para "n" elementos você precisa de pelo menos log2 (log2 (n)) ... (height-> log2 (n)) bits para armazenar a altura da árvore! Portanto, quando você está lidando com dados enormes, não pode ter certeza de quantos bits alocar para armazenar a altura em cada nó.

Por exemplo, se você usar 4 bytes int (32 bits) para armazenar a altura. A altura máxima pode ser: 2 ^ 32 e, portanto, o número máximo de elementos que você pode armazenar na árvore é 2 ^ (2 ^ 32) - (parece ser muito grande, mas nesta era de dados nada é muito grande, eu acho). Portanto, se você ultrapassar esse limite, terá que alocar dinamicamente mais espaço para armazenar a altura.

Esta é uma resposta sugerida por um professor da minha universidade que me pareceu razoável! Espero que eu faça sentido.

Edições: As árvores AVL são mais equilibradas em comparação com Red Black Trees, mas podem causar mais rotações durante a inserção e exclusão. Portanto, se o seu aplicativo envolve muitas inserções e exclusões frequentes, então as árvores Red Black devem ser preferidas. E se as inserções e exclusões são menos frequentes e a pesquisa é a operação mais frequente, então a árvore AVL deve ser preferida em vez da árvore Red Black. --Fonte GEEKSFORGEEKS.ORG


1
Eu diria que isso é interessante, mas pouco prático. Embora seja verdade que no caso mais compacto seria uma tarefa difícil escolher o número mais eficiente de bits para alocar para a altura, na prática, qualquer espaço restante que seja menor que um byte definitivamente não será usado, e qualquer coisa que sobrar em um espaço de 4 ou mesmo 8 bytes quase certamente não será usado. A memória não é alocada desalinhada por motivos de desempenho, substituindo muito o benefício de recuperar uma pequena quantidade de espaço. Os ponteiros para os filhos e o valor ocupam 24 bytes; 8 mais provavelmente não terão qualquer custo prático.
Mumbleskates

4
you need need atleast log2(log2(n))...(height->log2(n)) bits to store the height of [an AVL] treeEu não preciso da altura de qualquer nó em uma árvore AVL para implementá-lo. Você precisa de um bit de informação extra para cada nó ( EU SOU O MAIOR (o irmão com a subárvore mais alta))); é mais conveniente, bem como convencional, ter dois bits extras (a criança é mais alta para a esquerda e a direita), conforme apresentado por AV & L.
barba cinza

4
2 ^ (2 ^ 32) elementos é muito ... como se você pudesse armazenar cada molécula em todo o universo, e cada par possível dessas moléculas, e cada triplo possível, e ainda nem mesmo começar a chegar nem remotamente perto de estando dentro de uma minúscula fração de uma minúscula porcentagem da raiz cúbica desse número dividido por cem quintilhões.
ponto

4
Isso é muito enganoso. Primeiro, não precisamos armazenar a altura em um nó de uma árvore AVL. Em segundo lugar, mesmo que o fizéssemos, e mesmo que a quantidade típica de memória disponível dobre a cada ano, ainda teremos 4 bilhões de anos até que a altura de nossas árvores exceda o que pode ser armazenado em 32 bits.
Gassa

3
2 ^ (2 ^ 32) objetos é ridiculamente, insanamente, absolutamente mais do que qualquer computador que podemos imaginar agora pode conter. Estamos em algo como 2 ^ 40. Verifique se você é matemática novamente.
Stefan Reich

-1

O reequilíbrio da árvore AVL deve atender à propriedade abaixo. (Referência Wiki - Árvore AVL )

Em uma árvore AVL, as alturas das duas subárvores filhas de qualquer nó diferem em no máximo um; se a qualquer momento eles diferirem em mais de um, o rebalanceamento é feito para restaurar essa propriedade.

Portanto, isso implica que a altura geral da árvore AVL não pode enlouquecer, ou seja, as pesquisas serão melhores com Árvores AVL. E uma vez que operações adicionais (rotações) devem ser feitas para não deixar a altura enlouquecer, as operações de modificação da árvore podem ser um pouco caras.


Mencionou muitos outros lugares, mas a razão pela qual esta resposta não é muito boa é que árvores AVL e árvores RB efetivamente mantêm restrições extremamente semelhantes - árvores RB não terão mais do que 2,0 vezes a altura necessária, e para árvores AVL esse fator é cerca de 1,44. Como consequência, as árvores AVL giram um pouco mais frequentemente, mas o custo por rotação é essencialmente o mesmo; não é caro.
Mumbleskates
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.