Concatenando / Fusão / Unir duas árvores AVL
-
19-09-2019 - |
Pergunta
Suponha que eu tenho duas árvores AVL e que cada elemento da primeira árvore é menor, então qualquer elemento da segunda árvore. Qual é a maneira mais eficiente para concatenar-los em uma árvore AVL single? Eu procurei em todos os lugares, mas não encontraram nada de útil.
Solução
Assumindo que você pode destruir as árvores de entrada:
- remover o elemento mais à direita para a árvore esquerda, e usá-lo para construir um novo nó raiz, cujo filho esquerdo é a árvore esquerda, e cujo filho direito é a árvore direita: O (log n)
- determinar e definir esse fator de equilíbrio do nó: O (log n). Em violação (temporária) do invariante, o factor de equilíbrio pode estar fora da gama {-1, 0, 1}
- girar para obter o fator de volta o equilíbrio na gama: O (log n) rotações: O (log n)
Assim, toda a operação pode ser realizada em O (N log N).
Edit: Pensando bem, é mais fácil raciocinar sobre as rotações no seguinte algoritmo. Também é bastante provável mais rápido:
- determinar a altura de ambas as árvores:. O (log n)
Assumindo que a árvore certa é mais alto (o outro caso é simétrica): - remover o elemento mais à direita da árvore
left
(rotação e ajustar a sua altura computadorizada se necessário). Vamosn
ser esse elemento. O (N log N) - Na árvore direita, navegar esquerda até chegar a um nó cujo subárvore é no máximo um 1 mais alto do que
left
. Vamosr
ser esse nó. O (N log N) -
substituir esse nó com um novo nó com o valor de n, e subárvores
left
er
. O (1)
Por construção, o novo nó é AVL balanceada, e seu mais alto sub 1 der
. -
incrementar o equilíbrio do seu pai em conformidade. O (1)
- e reequilíbrio, como você faria depois de inserir. O (N log N)
Outras dicas
Uma solução ultra-simples (que funciona sem quaisquer suposições nas relações entre as árvores) é o seguinte:
- Faça um merge sort de ambas as árvores em um array fundido (simultaneamente iterate ambas as árvores).
- Criar uma árvore AVL da matriz -. Levar o elemento do meio para ser a raiz, e aplicar de forma recursiva para metades direita e esquerda
Ambos os passos são O (n). O grande problema com isso é que leva O (n) espaço extra.
A melhor solução que eu li para este problema pode ser encontrada aqui . Está muito perto de resposta meriton 's se você corrigir esse problema:
No terceiro passo do algoritmo navega esquerda até chegar o nó cuja árvore sub tem a mesma altura da árvore esquerda . Isso nem sempre é possível, (veja a imagem contra-exemplo). O caminho certo para fazer esta etapa é de dois achado para uma sub-árvore com h
altura ou h+1
onde h
é a altura da árvore esquerda
Eu suspeito que você só tem que andar uma árvore (esperemos que o menor) e individualmente adicionar cada um de seus elementos para a outra árvore. As operações de exclusão / AVL insert não são projetados para lidar com a adição de uma sub-árvore toda de uma vez.