it-swarm.com.de

Javascript Array.sort Implementierung?

Welchen Algorithmus verwendet die Funktion JavaScript Array#sort()? Ich verstehe, dass es allerlei Argumente und Funktionen erfordern kann, um verschiedene Arten von Sortierungen durchzuführen. Mich interessiert einfach, welchen Algorithmus die Vanilla-Sortierung verwendet.

205
latortuga

Wenn Sie sich diesen Fehler ansehen 224128 , scheint MergeSort von Mozilla verwendet zu werden.

62
Britton

Ich habe mir gerade das WebKit (Chrome, Safari…) angesehen Quelle . Abhängig vom Typ des Arrays werden verschiedene Sortiermethoden verwendet:

Numerische Arrays (oder Arrays vom primitiven Typ) werden mit der C++ - Standardbibliotheksfunktion sortiert std::qsort welches eine Variation von Quicksort implementiert (normalerweise Introsort ).

Aneinandergrenzende Arrays von nicht numerischem Typ werden mithilfe von Mergesort (falls verfügbar) (um eine stabile Sortierung zu erhalten) oder qsort (falls keine Sortierung für die Zusammenführung verfügbar ist) stringifiziert und sortiert.

Für andere Typen (nicht zusammenhängende Arrays und vermutlich assoziative Arrays) verwendet WebKit entweder Auswahlsortierung (die sie "Min" -Sortierung nennen) oder, in einigen Fällen, eine Sortierung über einen AVL-Baum. Leider ist die Dokumentation hier ziemlich vage, sodass Sie die Codepfade nachverfolgen müssen, um tatsächlich zu sehen, für welche Typen welche Sortiermethode verwendet wird.

Und dann gibt es Edelsteine ​​wie dieser Kommentar :

// FIXME: Since we sort by string value, a fast algorithm might be to use a
// radix sort. That would be O(N) rather than O(N log N).

- Hoffen wir einfach, dass derjenige, der dies tatsächlich "behebt", die asymptotische Laufzeit besser versteht als der Verfasser dieses Kommentars und erkennt, dass Radix-Sortierung hat eine etwas komplexere Laufzeitbeschreibung als einfach O (N) .

(Danke an phsource für den Hinweis auf den Fehler in der ursprünglichen Antwort.)

270
Konrad Rudolph

Es gibt keinen Entwurf, wonach JS einen bestimmten Sortieralgorithmus verwenden muss. Wie viele hier bereits erwähnt haben, verwendet Mozilla Merge Sort. Im aktuellen Chrome-Quellcode v8 werden jedoch QuickSort und InsertionSort für kleinere Arrays verwendet.

V8-Motorquelle

Von den Linien 807 - 891

  var QuickSort = function QuickSort(a, from, to) {
    var third_index = 0;
    while (true) {
      // Insertion sort is faster for short arrays.
      if (to - from <= 10) {
        InsertionSort(a, from, to);
        return;
      }
      if (to - from > 1000) {
        third_index = GetThirdIndex(a, from, to);
      } else {
        third_index = from + ((to - from) >> 1);
      }
      // Find a pivot as the median of first, last and middle element.
      var v0 = a[from];
      var v1 = a[to - 1];
      var v2 = a[third_index];
      var c01 = comparefn(v0, v1);
      if (c01 > 0) {
        // v1 < v0, so swap them.
        var tmp = v0;
        v0 = v1;
        v1 = tmp;
      } // v0 <= v1.
      var c02 = comparefn(v0, v2);
      if (c02 >= 0) {
        // v2 <= v0 <= v1.
        var tmp = v0;
        v0 = v2;
        v2 = v1;
        v1 = tmp;
      } else {
        // v0 <= v1 && v0 < v2
        var c12 = comparefn(v1, v2);
        if (c12 > 0) {
          // v0 <= v2 < v1
          var tmp = v1;
          v1 = v2;
          v2 = tmp;
        }
      }
      // v0 <= v1 <= v2
      a[from] = v0;
      a[to - 1] = v2;
      var pivot = v1;
      var low_end = from + 1;   // Upper bound of elements lower than pivot.
      var high_start = to - 1;  // Lower bound of elements greater than pivot.
      a[third_index] = a[low_end];
      a[low_end] = pivot;

      // From low_end to i are elements equal to pivot.
      // From i to high_start are elements that haven't been compared yet.
      partition: for (var i = low_end + 1; i < high_start; i++) {
        var element = a[i];
        var order = comparefn(element, pivot);
        if (order < 0) {
          a[i] = a[low_end];
          a[low_end] = element;
          low_end++;
        } else if (order > 0) {
          do {
            high_start--;
            if (high_start == i) break partition;
            var top_elem = a[high_start];
            order = comparefn(top_elem, pivot);
          } while (order > 0);
          a[i] = a[high_start];
          a[high_start] = element;
          if (order < 0) {
            element = a[i];
            a[i] = a[low_end];
            a[low_end] = element;
            low_end++;
          }
        }
      }
      if (to - high_start < low_end - from) {
        QuickSort(a, high_start, to);
        to = low_end;
      } else {
        QuickSort(a, from, low_end);
        from = high_start;
      }
    }
  };

Update Ab 2018 nutzt V8 TimSort, danke @celwell. Quelle

34
Joe Thomas

Der ECMAscript-Standard gibt nicht an, welcher Sortieralgorithmus verwendet werden soll. In der Tat verfügen verschiedene Browser über unterschiedliche Sortieralgorithmen. Zum Beispiel ist Mozilla/Firefox sort () nicht stabil (im Sinne des Wortes sortierend), wenn eine Karte sortiert wird. IE's sort () ist stabil.

23
Steve

Nach weiteren Recherchen scheint es für Mozilla/Firefox, dass Array.sort () mergesort verwendet. Siehe den Code hier .

9
latortuga

Ich denke, das würde davon abhängen, auf welche Browser-Implementierung Sie sich beziehen.

Jeder Browsertyp hat eine eigene JavaScript-Engine-Implementierung, das hängt also davon ab. Sie können die Quellcode-Repos für Mozilla und Webkit/Khtml auf verschiedene Implementierungen überprüfen.

IE ist jedoch eine geschlossene Quelle, so dass Sie möglicherweise jemanden bei Microsoft fragen müssen.

8
Huibert Gill

Ab V8 v7.0/Chrome 70) verwendet V8 TimSort , den Sortieralgorithmus von Python. Chrome 70) wurde am 13. September veröffentlicht 2018.

Weitere Informationen zu dieser Änderung finden Sie in dem Beitrag im V8-Dev-Blog . Sie können auch den Quellcode oder Patch 1186801 lesen.

3
Boris

Die Array.sort () - Funktion von JavaScript verfügt über interne Mechanismen zur Auswahl des besten Sortieralgorithmus (QuickSort, MergeSort usw.) auf der Grundlage des Datentyps der Array-Elemente.

0