Warum ist Mergesort O (log n)?

27

Mergesort ist ein Divisions- und Eroberungsalgorithmus und ist O (log n), da die Eingabe wiederholt halbiert wird. Aber sollte es nicht O (n) sein, weil, obwohl die Eingabe in jeder Schleife halbiert wird, jedes Eingabeelement iteriert werden muss, um das Austauschen in jedem halbierten Array durchzuführen? Dies ist meiner Meinung nach im Wesentlichen asymptotisch O (n). Geben Sie nach Möglichkeit Beispiele und erläutern Sie, wie Sie die Vorgänge richtig zählen! Ich habe noch nichts geschrieben, aber ich habe online nach Algorithmen gesucht. Ich habe auch ein GIF von Wikipedia angehängt, um visuell zu zeigen, wie Mergesort funktioniert.

Bildbeschreibung hier eingeben

Ausdauer
quelle
33
Es ist O (n log n)
Esben Skov Pedersen
18
Sogar Gottes Sortieralgorithmus (ein hypothetischer Sortieralgorithmus, der Zugang zu einem Orakel hat, das ihm sagt, wo jedes Element hingehört) hat eine Laufzeit von O (n), weil er jedes Element, das sich in einer falschen Position befindet, mindestens einmal verschieben muss.
Philipp

Antworten:

59

Es ist O (n * log (n)), nicht O (log (n)). Wie Sie genau vermutet haben, muss die gesamte Eingabe durchlaufen werden, und dies muss O-mal (log (n)) erfolgen (die Eingabe kann nur O-mal (log (n)) halbiert werden). n Elemente, die log (n) mal iteriert wurden, ergeben O (n log (n)).

Es ist bewiesen, dass keine Vergleichssorte schneller arbeiten kann. Nur Sortierungen, die sich auf eine spezielle Eigenschaft der Eingabe stützen, z. B. die Radix-Sortierung, können diese Komplexität übertreffen. Die konstanten Faktoren von Mergesort sind in der Regel jedoch nicht so groß, sodass Algorithmen mit geringerer Komplexität häufig weniger Zeit in Anspruch nehmen können.

DeadMG
quelle
3
s / schneller / mit geringerer Komplexität /
jk.
33

Die Komplexität der Zusammenführungssortierung ist O (nlogn) und NOT O (logn).

Merge Sort ist ein Divide-and-Conquer-Algorithmus. Denken Sie in 3 Schritten darüber nach -

  1. Der Teilungsschritt berechnet den Mittelpunkt jeder der Unteranordnungen. Jeder dieser Schritte benötigt nur O (1) Zeit.
  2. Der Eroberungsschritt sortiert rekursiv zwei Unterfelder mit jeweils n / 2 (für gerade n) Elementen.
  3. Der Zusammenführungsschritt führt n Elemente zusammen, was O (n) Zeit in Anspruch nimmt.

Für die Schritte 1 und 3, dh zwischen O (1) und O (n), ist O (n) höher. Nehmen wir an, dass die Schritte 1 und 3 insgesamt 0 (n) Zeit benötigen. Angenommen, es ist cn für eine Konstante c.

Wie oft werden diese Schritte ausgeführt?

Schauen Sie sich dazu den Baum unten an - für jede Ebene von oben nach unten die Methode zum Zusammenführen von Aufrufen der Ebene 2 für 2 Unterarrays mit einer Länge von jeweils n / 2. Die Komplexität beträgt hier 2 * (cn / 2) = cn Die Methode zum Zusammenführen von Aufrufen der Ebene 3 für 4 Unterarrays mit einer Länge von jeweils n / 4. Die Komplexität hier ist 4 * (cn / 4) = cn und so weiter ...

Nun ist die Höhe dieses Baumes (logn + 1) für ein gegebenes n. Somit ist die Gesamtkomplexität (logn + 1) * (cn). Das ist O (nlogn) für den Mergesortierungsalgorithmus.

Sortierung für n Elemente zusammenfassen

Bildnachweis: Khan Academy

Shantanu Alshi
quelle
9

Merge Sort ist ein rekursiver Algorithmus und die Zeitkomplexität kann wie folgt ausgedrückt werden:

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

Die obige Wiederholung kann entweder mit der Recurrence Tree-Methode oder der Master-Methode gelöst werden. Es fällt in den Fall II der Master-Methode und die Lösung der Wiederholung ist ɵ (n log n).

Die zeitliche Komplexität der Zusammenführungssortierung beträgt in allen drei Fällen (schlechteste, durchschnittliche und beste) ɵ (nLogn), da die Zusammenführungssortierung das Array immer in zwei Hälften teilt und für die Zusammenführung von zwei Hälften lineare Zeit benötigt.

Es teilt das Eingabearray in zwei Hälften, ruft sich selbst für die beiden Hälften auf und führt dann die beiden sortierten Hälften zusammen. Mit der Funktion merg () werden zwei Hälften zusammengeführt. Das Zusammenführen (arr, l, m, r) ist ein Schlüsselprozess, der davon ausgeht, dass arr [l..m] und arr [m + 1..r] sortiert sind, und die beiden sortierten Unterarrays zu einem zusammenführt. Weitere Informationen finden Sie in der folgenden C-Implementierung.

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)

Bildbeschreibung hier eingeben

Wenn wir uns das Diagramm genauer ansehen, können wir sehen, dass das Array rekursiv in zwei Hälften geteilt wird, bis die Größe 1 wird. Sobald die Größe 1 wird, wird der Zusammenführungsprozess aktiviert und das Zusammenführen der Arrays beginnt, bis das gesamte Array wieder vorhanden ist zusammengeführt.

Nishant Sethi
quelle
1
Könnten Sie die Art des Zusammenführungsteils erläutern und erläutern, wie er zur Leistung von O (n log n) beiträgt?
Die Komplexität der Zusammenführungsfunktion ist O (n), da 2 Arrays als Eingabe verwendet werden, die verglichen und in new ausgegeben werden. Wenn jedes Element mit jedem anderen Element im Array verglichen wird, ergibt sich für die Komplexität dieser Zusammenführungsfunktion O (n).
Nishant Sethi
1
Ich liebe diese Visualisierung der Art!
spaaarky21
0

Vergleichsbasierte Sortieralgorithmen haben eine Untergrenze 𝞨(n*log(n)), was bedeutet, dass es nicht möglich ist, einen vergleichsbasierten Sortieralgorithmus mit O(log(n))zeitlicher Komplexität zu verwenden.

Übrigens ist Merge Sort O(n*log(n)). Denk es so.

[ 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''''

Dies sieht nach einem umgekehrten binären Baum aus.

Die Eingabegröße sei n.

Jedes a_nrepräsentiert eine Liste von Elementen. Erste Zeile a_nhat nur ein Element.

Auf jeder Ebene beträgt die Summe der Zusammenführungskosten im Durchschnitt n(es gibt Eckfälle, bei denen die Kosten niedriger sind [1]). Und die Höhe des Baumes ist log_2(n).

Die zeitliche Komplexität der Zusammenführungssortierung ist also O(n*log_2(n)).

[1] Wenn Sie nach einer Liste sortieren, die bereits sortiert ist, wird dies als bester Fall bezeichnet. die kosten sanken auf n/2 + n/4 + n/8 + .... + 1 = 2^log_2(n) -1 ~ O(n). (Angenommen, die Länge nist Potenz von zwei)

W. PC
quelle
-2

Das Sortieren ist ein NP-vollständiges Problem in der Informatik (nichtpolynomielles Problem). Dies bedeutet, dass Sie beim Sortieren einer Liste von Elementen nicht unter O (n log n) gehen können, es sei denn, dies ist mathematisch bewiesen.

Überprüfen Sie diesen Artikel in Wikipedia ( https://en.wikipedia.org/wiki/P_versus_NP_problem )

Im Grunde ist es bisher niemandem gelungen, dies zu beweisen (P == NP), und wenn Sie dies tun, werden Sie erstens Millionär, zweitens starten Sie den dritten Weltkrieg, da Sie in der Lage sind, alle verwendeten Sicherheitsmechanismen für Kneipen- / private Schlüssel zu unterbrechen heutzutage überall :)

slux83
quelle
2
Das ist nicht was NP bedeutet. Sogar BubbleSort ist in P. Man muss sich sehr bemühen, eine Sortierung zu erstellen, die nicht in P ist (zB BogoSort)
Caleth