Mergesort est un algorithme de division et de conquête et est O (log n) car l'entrée est divisée par deux à plusieurs reprises. Mais ne devrait-il pas être O(n) parce que même si l'entrée est divisée par deux par boucle, chaque élément d'entrée doit être itéré pour effectuer l'échange dans chaque tableau divisé par deux? C'est essentiellement asymptotiquement O(n) dans mon esprit. Si possible, veuillez fournir des exemples et expliquer comment compter les opérations correctement! Je n'ai encore rien codé mais j'ai consulté des algorithmes en ligne. I 'ai également joint un gif de ce que wikipedia utilise pour montrer visuellement comment fonctionne le mergesort.
C'est O (n * log (n)), pas O (log (n)). Comme vous l'avez deviné, toute l'entrée doit être itérée, et cela doit se produire O(log(n)) fois (l'entrée ne peut être divisée qu'en deux O(log(n)) fois). n éléments itéré journal (n) fois donne O (n log (n)).
Il a été prouvé qu'aucun tri par comparaison ne peut fonctionner plus rapidement que cela. Seuls les tris qui reposent sur une propriété spéciale de l'entrée, comme le tri radix, peuvent battre cette complexité. Les facteurs constants du fusionnement ne sont généralement pas si bons que cela, donc les algorithmes avec une complexité pire peuvent souvent prendre moins de temps.
La complexité du tri par fusion est O(nlogn) et PAS O (logn).
Le tri par fusion est un algorithme de division et de conquête. Pensez-y en termes de 3 étapes -
Maintenant, pour les étapes 1 et 3, c'est-à-dire entre O(1) et O (n), O(n) est plus élevé. Considérons les étapes 1 et 3 prendre O(n) temps au total. Disons que c'est cn pour une constante c.
Combien de fois ces étapes sont-elles exécutées?
Pour cela, regardez l'arborescence ci-dessous - pour chaque niveau de haut en bas, la méthode de fusion des appels de niveau 2 sur 2 sous-tableaux de longueur n/2 chacun. La complexité ici est de 2 * (cn/2) = cn Méthode de fusion des appels de niveau 3 sur 4 sous-tableaux de longueur n/4 chacun. La complexité ici est 4 * (cn/4) = cn et ainsi de suite ...
Maintenant, la hauteur de cet arbre est (logn + 1) pour un n donné. Ainsi, la complexité globale est (logn + 1) * (cn). C'est O(nlogn) pour l'algorithme de tri par fusion.
Crédits image: Khan Academy
Merge Sort est un algorithme récursif et la complexité temporelle peut être exprimée comme suit la relation de récurrence.
T(n) = 2T(n/2) + ɵ(n)
La récurrence ci-dessus peut être résolue en utilisant la méthode de l'arbre de récurrence ou la méthode principale. Elle tombe dans le cas II de la méthode maître et la solution de la récurrence est ɵ (n log n).
La complexité temporelle du tri par fusion est ɵ (nLogn) dans les 3 cas (pire, moyen et meilleur) car le tri par fusion divise toujours le tableau en deux moitiés et prend un temps linéaire pour fusionner deux moitiés.
Il divise le tableau d'entrée en deux moitiés, s'appelle lui-même pour les deux moitiés, puis fusionne les deux moitiés triées. La fonction merg () est utilisée pour fusionner deux moitiés. La fusion (arr, l, m, r) est un processus clé qui suppose que arr [l..m] et arr [m + 1..r] sont triés et fusionne les deux sous-tableaux triés en un seul. Voir l'implémentation C suivante pour plus de détails.
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)
Si nous regardons de plus près le diagramme, nous pouvons voir que le tableau est récursivement divisé en deux moitiés jusqu'à ce que la taille devienne 1. Une fois que la taille devient 1, le processus de fusion entre en action et commence à fusionner les tableaux jusqu'à ce que le tableau complet soit fusionné.
Les algorithmes de tri basés sur la comparaison ont une limite inférieure ????(n*log(n))
, ce qui signifie qu'il n'est pas possible d'avoir un algorithme de tri basé sur la comparaison avec la complexité temporelle O(log(n))
.
Par ailleurs, le tri par fusion est O(n*log(n))
. Pensez-y de cette façon.
[ 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''''
Cela ressemble à un arbre binaire inversé.
Laissez la taille d'entrée être n
.
Chaque a_n
Représente une liste d'éléments. Le a_n
De la première ligne n'a qu'un seul élément.
A chaque niveau, la somme du coût de fusion est en moyenne n
(il existe des cas d'angle dont le coût est inférieur [1]). Et la hauteur de l'arbre est log_2(n)
.
Ainsi, la complexité temporelle du tri par fusion est O(n*log_2(n))
.
[1] si tri sur une liste déjà triée, ce qui est appelé le meilleur cas. le coût réduit à
n/2 + n/4 + n/8 + .... + 1 = 2^log_2(n) -1 ~ O(n)
. (supposez que la longueurn
est une puissance de deux)