Por que o mergesort O (log n)?

27

Mergesort é um algoritmo de divisão e conquista e é O (log n) porque a entrada é dividida repetidamente pela metade. Mas não deveria ser O (n) porque, embora a entrada seja dividida pela metade em cada loop, cada item de entrada precisa ser iterado para fazer a troca em cada matriz dividida pela metade? Isso é essencialmente assintoticamente O (n) em minha mente. Se possível, forneça exemplos e explique como contar as operações corretamente! Ainda não codifiquei nada, mas estive pesquisando algoritmos online. Também anexei um gif do que a wikipedia está usando para mostrar visualmente como o mergesort funciona.

insira a descrição da imagem aqui

perseverança
fonte
33
É O (n log n)
Esben Skov Pedersen
18
Mesmo o algoritmo de classificação de deus (um algoritmo de classificação hipotético que tem acesso a um oráculo que diz aonde cada elemento pertence) tem um tempo de execução de O (n) porque ele precisa mover cada elemento que está na posição errada pelo menos uma vez.
Philipp

Respostas:

59

É O (n * log (n)), não O (log (n)). Como você supôs com precisão, toda a entrada deve ser iterada e isso deve ocorrer O (log (n)) vezes (a entrada só pode ser reduzida pela metade O (log (n)) vezes). n itens iterados log (n) vezes fornece O (n log (n)).

Está provado que nenhum tipo de comparação pode operar mais rápido que isso. Somente classificações que dependem de uma propriedade especial da entrada, como classificação de base, podem superar essa complexidade. Os fatores constantes do mergesort normalmente não são tão grandes, embora algoritmos com pior complexidade geralmente levem menos tempo.

DeadMG
fonte
3
s / mais rápido / com menor complexidade /
jk.
33

A complexidade da classificação de mesclagem é O (nlogn) e NÃO O (logn).

A classificação de mesclagem é um algoritmo de divisão e conquista. Pense nisso em termos de três etapas -

  1. A etapa de divisão calcula o ponto médio de cada uma das sub-matrizes. Cada uma dessas etapas leva apenas O (1) tempo.
  2. A etapa de conquista classifica recursivamente duas sub-matrizes de n / 2 (para até n) elementos cada.
  3. A etapa de mesclagem mescla n elementos que levam tempo O (n).

Agora, para as etapas 1 e 3, ou seja, entre O (1) e O (n), O (n) é maior. Vamos considerar as etapas 1 e 3 que levam O (n) tempo no total. Diga que é cn por alguma constante c.

Quantas vezes essas etapas são executadas?

Para isso, observe a árvore abaixo - para cada nível de cima para baixo, o nível 2 chama o método de mesclagem em 2 sub-matrizes de comprimento n / 2 cada. A complexidade aqui é 2 * (cn / 2) = cn O nível 3 chama o método de mesclagem em 4 sub-matrizes de comprimento n / 4 cada. A complexidade aqui é 4 * (cn / 4) = cn e assim por diante ...

Agora, a altura desta árvore é (logn + 1) para um dado n. Portanto, a complexidade geral é (logn + 1) * (cn). Isso é O (nlogn) para o algoritmo de classificação de mesclagem.

Mesclar classificação para n elementos

Créditos da imagem: Khan Academy

Shantanu Alshi
fonte
9

A classificação de mesclagem é um algoritmo recursivo e a complexidade do tempo pode ser expressa como a seguinte relação de recorrência.

T (n) = 2T (n / 2) + ɵ (n)

A recorrência acima pode ser resolvida usando o método Recurrence Tree ou Master. Está no caso II do método mestre e a solução da recorrência é ɵ (n log n).

A complexidade de tempo da Merge Sort é ɵ (nLogn) nos 3 casos (pior, médio e melhor), pois a classificação de mesclagem sempre divide o array em duas metades e leva um tempo linear para mesclar duas metades.

Ele divide a matriz de entrada em duas metades, chama-se pelas duas metades e depois mescla as duas metades classificadas. A função merg () é usada para mesclar duas metades. A mesclagem (arr, l, m, r) é um processo-chave que pressupõe que arr [l..m] e arr [m + 1..r] são classificados e mescla os dois sub-vetores classificados em um. Consulte a seguinte implementação em C para obter detalhes.

MergeSort(arr[], l,  r)
If r > l
     1. Find the middle point to divide the array into two halves:  
             middle m = (l+r)/2
     2. Call mergeSort for first half:   
             Call mergeSort(arr, l, m)
     3. Call mergeSort for second half:
             Call mergeSort(arr, m+1, r)
     4. Merge the two halves sorted in step 2 and 3:
             Call merge(arr, l, m, r)

insira a descrição da imagem aqui

Se olharmos mais de perto o diagrama, podemos ver que a matriz é recursivamente dividida em duas metades até o tamanho se tornar 1. Quando o tamanho se torna 1, os processos de mesclagem entram em ação e começam a mesclar as matrizes até a matriz completa ser concluída. mesclado.

Nishant sethi
fonte
1
Você poderia elaborar a natureza da parte de mesclagem e como ela contribui para o desempenho de O (n log n)?
A complexidade da função de mesclagem é O (n), pois é necessário 2 matrizes como entrada, compará-las e fornecer saída em novo. Como ele está comparando cada elemento com todos os outros elementos da matriz, a complexidade dessa função de mesclagem acaba sendo O (n).
Nishant sethi
1
Eu amo essa visualização do tipo!
spaaarky21
0

Os algoritmos de classificação baseados em comparação têm um limite inferior 𝞨(n*log(n)), o que significa que não é possível ter um algoritmo de classificação baseado em comparação com O(log(n))complexidade de tempo.

A propósito, a ordem de mesclagem é O(n*log(n)). Pense assim.

[ a1,a2,         a3,a4,         a5,a6,          a7,a8     .... an-3,an-2,     an-1, an ] 
   \ /            \  /           \ /             \  /            \  /            \  /    
    a1'            a3'            a5'             a7'            an-3'           an-1'    
      \            /                \             /                 \             /
            a1''                          a5''                       an-3''
             \                             /                         /
                          a1'''                                     /
                           \
                                              a1''''

Parece uma árvore binária invertida.

Deixe o tamanho da entrada ser n.

Cada a_num representa uma lista de elementos. A primeira linha a_ntem apenas um elemento.

Em cada nível, a soma do custo de mesclagem, em média, é n(existem casos de canto cujo custo é menor [1]). E a altura da árvore é log_2(n).

Portanto, a complexidade do tempo da classificação por mesclagem é O(n*log_2(n)).

[1] se estiver classificando em uma lista que já está classificada, chamada de melhor caso. o custo reduzido para n/2 + n/4 + n/8 + .... + 1 = 2^log_2(n) -1 ~ O(n). (suponha que o comprimento nseja poder de dois)

W. PC
fonte
-2

A classificação é um problema NP-Complete em ciência da computação (problema não polinomial). Isso significa que, a menos que seja matematicamente comprovado, você não pode ficar abaixo de O (n log n) ao classificar uma lista de elementos.

Verifique este artigo na Wikipedia ( https://en.wikipedia.org/wiki/P_versus_NP_problem )

Basicamente, até agora ninguém conseguiu provar isso (P == NP) e, se o fizer, você se torna milionário, depois começa a Terceira Guerra Mundial, devido ao fato de que será capaz de quebrar todos os mecanismos de segurança de pub / chave privada usados em todos os lugares hoje em dia :)

slux83
fonte
2
Não é isso que NP significa. Até o BubbleSort está em P. Você precisa se esforçar para fazer um tipo que não esteja em P (por exemplo, BogoSort)
Caleth