Dadas duas matrizes ordenadas a , b do tipo T com tamanho n e m . Estou procurando um algoritmo que mescla as duas matrizes em uma nova matriz (de tamanho máximo n + m).
Se você tem uma operação de comparação barata, isso é bastante simples. Apenas retire da matriz com o primeiro elemento mais baixo até que uma ou ambas as matrizes sejam atravessadas completamente e adicione os elementos restantes. Algo como este /programming/5958169/how-to-merge-two-sorted-arrays-into-a-sorted-array
No entanto, a situação muda ao comparar dois elementos, é muito mais caro do que copiar um elemento da matriz de origem para a matriz de destino . Por exemplo, você pode ter uma matriz de grandes números inteiros de precisão arbitrária, ou seqüências de caracteres, onde uma comparação pode ser bastante cara. Suponha que a criação de matrizes e cópia de elementos seja gratuita e a única coisa que custa é comparar elementos.
Nesse caso, você deseja mesclar as duas matrizes com um número mínimo de comparações de elementos . Aqui estão alguns exemplos em que você deve fazer muito melhor do que o algoritmo de mesclagem simples:
a = [1,2,3,4, ... 1000]
b = [1001,1002,1003,1004, ... 2000]
Ou
a = [1,2,3,4, ... 1000]
b = [0,100,200, ... 1000]
Existem alguns casos em que o algoritmo de mesclagem simples será ideal, como
a = [1,3,5,7,9,....,999]
b = [2,4,6,8,10,....,1000]
Portanto, o algoritmo idealmente deve degradar e executar no máximo n + m-1 comparações caso as matrizes sejam intercaladas ou, pelo menos, não sejam significativamente piores.
Uma coisa que deve funcionar muito bem para listas com uma grande diferença de tamanho seria usar a pesquisa binária para inserir os elementos da matriz menor na matriz maior. Mas isso não será degradado se as duas listas forem do mesmo tamanho e intercaladas.
A única coisa disponível para os elementos é uma função de pedido (total), portanto, qualquer esquema que torne as comparações mais baratas não é possível.
Alguma ideia?
Eu vim com essa parte em Scala . Eu acredito que é ótimo em relação ao número de comparações, mas está além da minha capacidade de provar isso. Pelo menos, é muito mais simples do que as coisas que encontrei na literatura.
E desde a postagem original, escrevi uma postagem no blog sobre como isso funciona.
fonte
Respostas:
O algoritmo normal de classificação de mesclagem - etapa de mesclagem normalmente aplica comparações n + m -1, em que uma lista é do tamanho n e a outra lista é do tamanho m. O uso desse algoritmo é a abordagem mais simples para combinar duas listas classificadas.
Se as comparações forem muito caras, você poderá fazer duas coisas - minimizar o número de comparações ou minimizar o custo das comparações.
Vamos nos concentrar na minimização do custo de comparação. Você e somente você pode decidir se os dados que você está comparando podem ser quantizados ou não. Se você pode quantizá-los, é uma forma de implementar um método hash, que está mantendo a ordem. Por exemplo, se seus dados são comparados por nome, então o primeiro tname, ... você pode levar o primeiro a Chars com o nome "Klaehn, Ruediger" e reduzir / quantizar seu elemento de dados para "Kl.Ru", se você o comparar para "Empacotador, O", você preserva a ordem "Pa.Th" - agora você pode aplicar um algoritmo de comparação mais barato, comparando os valores reduzidos. Mas se você encontrar outro "Kl.Ru", agora terá um valor próximo e poderá agora mudar para uma abordagem mais cara comparando esses elementos.
Se você pode extrair esse valor quantizado dos seus dados, mais rapidamente do que compará-lo, é a primeira coisa que faz, você compara o valor quantizado ou o hash primeiro. Lembre-se de que esse valor precisa ser calculado apenas uma vez, para que você possa calculá-lo ao criar o elemento de dados.
Eu também mencionei outra maneira, para minimizar suas comparações.
Dei uma olhada no livro clássico TAOCP - Volume 3 - Classificação e pesquisa (pp.197-207, seção 5.3.2), que tem 10 páginas completas sobre esse tópico. Encontrei duas referências a algoritmos que são mais rápidos que as comparações n + m-1.
Primeiro, há o algoritmo de mesclagem Hwang-Lin e o segundo, uma melhoria de Glenn K Manacher - ambos são citados pelo TAOCP e também um algoritmo de Christen, que se aproxima do limite inferior das comparações necessárias, em condições especiais no comprimento ne das listas.
O algoritmo de Manacher foi apresentado no Journal of the ACM Vol. 26 Número 3 nas páginas 434-440: "Melhorias significativas no algoritmo de mesclagem" Hwan-Lin "". a lista com m itens e a lista com n itens podem ter tamanhos diferentes, mas também devem ser odiadas pelo número de elementos que contêm m <= n
O algoritmo Hwang-Lin divide as listas para mesclar, além de listas menores e classifica as listas, comparando o primeiro elemento de cada sub-lista e para decidir se alguns elementos na sub-lista precisam ser comparados ou não. Se a primeira lista for menor que a segunda, a chance é alta de que elementos consecutivos da lista mais longa possam ser transferidos para a lista resultante sem comparação. Se o primeiro elemento do pequeno ist for maior que o primeiro elemento da lista maior dividida, todos os elementos na frente da sublist poderão ser copiados sem comparação.
Análise de caso médio do aloritmo de fusão de Hwang e Lin (Vega, Frieze, Santha) na Seção 2, você pode encontrar um pseudocódigo do algoritmo HL. O que é muito melhor que a minha descrição. E você pode ver por que há menos comparações - o algoritmo usa uma pesquisa binária, para encontrar o índice, onde inserir o elemento da lista mais curta.
Se as listas não forem intercaladas como no seu último exemplo, na maioria dos casos você deverá ter uma lista menor e outra maior. É quando o algoritmo HL começa a funcionar melhor.
fonte
Suponha que as duas matrizes tenham elementos N e M, N ≥ M, e todos os elementos sejam diferentes.
Se a matriz classificada contiver um elemento x de N seguido por um elemento y de M ou vice-versa, então xey deverão ter sido comparados; caso contrário, não saberíamos em que ordem eles pertencem. (Não pode haver uma cadeia de outros elementos, digamos a, b, c, onde sabemos que x <a <b <c <y, por exemplo, porque não existem elementos entre x e y. Portanto, x e y devem ter sido comparados diretamente.
Se N> M, é possível ter uma matriz em que cada elemento de M seja precedido e seguido por um elemento de N, o que significa que são necessárias pelo menos 2 milhões de comparações - mesmo se você usar um algoritmo de classificação não determinístico que possa fazer um palpite perfeito de quais números comparar. (O que isso significa: suponha que você tenha N grande, M = 1. A pesquisa binária executa etapas O (log2 N); um algoritmo não determinístico poderia adivinhar entre quais dois elementos o elemento da segunda matriz pertence e fazer duas comparações com confirme a suposição).
fonte