[javascript] 자바 스크립트 Array.Sort 구현?

JavaScript Array#sort()함수 는 어떤 알고리즘을 사용합니까? 다른 종류의 정렬을 수행하는 데 모든 방식의 인수와 함수가 필요할 수 있음을 이해합니다. 바닐라 정렬이 사용하는 알고리즘에 관심이 있습니다.



답변

이 버그 224128 을 보면 MergeSort가 Mozilla에서 사용중인 것 같습니다.


답변

방금 WebKit (Chrome, Safari…) 소스를 살펴 보았습니다 . 배열 유형에 따라 다른 정렬 방법이 사용됩니다.

숫자 형 배열 (또는 기본 유형의 배열)은 C ++ 표준 라이브러리 함수 std::qsort를 사용하여 정렬되어 퀵 정렬 (보통 introsort )의 변형을 구현 합니다.

숫자가 아닌 유형의 연속 배열은 사용 가능한 경우 (안정적인 정렬을 얻기 위해) 또는 qsort사용 가능한 병합 정렬이없는 경우 mergesort를 사용하여 문자열 화되고 정렬 됩니다.

다른 유형 (인접하지 않은 배열 및 아마도 연관 배열의 경우) WebKit은 선택 정렬 ( “min”sort이라고 함 )을 사용하거나 경우에 따라 AVL 트리를 통해 정렬합니다. 불행히도 여기 문서는 다소 모호하므로 실제로 어떤 종류의 정렬 방법이 사용되는지 코드 경로를 추적해야합니다.

그리고이 주석 과 같은 보석 이 있습니다 :

// 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).

– 실제로 이것을 “수정”하는 사람이이 주석의 작성자보다 점근 적 런타임에 대해 더 잘 이해하고 기수 정렬이 단순히 O (N)보다 약간 더 복잡한 런타임 설명을 가지고 있음을 깨닫기를 바랍니다 .

(원래 답변의 오류를 지적한 phsource에게 감사합니다.)


답변

JS가 특정 정렬 알고리즘을 사용해야하는 초안 요구 사항은 없습니다. 많은 사람들이 여기에서 언급했듯이 Mozilla는 병합 정렬을 사용하지만 오늘날 Chrome의 v8 소스 코드에서는 더 작은 배열에 QuickSort 및 InsertionSort를 사용합니다.

V8 엔진 소스

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;
      }
    }
  };

업데이트
2018 V8은 @celwell 덕분에 TimSort를 사용합니다. 출처


답변

ECMAscript 표준은 사용할 정렬 알고리즘을 지정하지 않습니다. 실제로 브라우저마다 다른 정렬 알고리즘이 있습니다. 예를 들어, 지도를 정렬 할 때 Mozilla / Firefox의 sort ()는 단어의 정렬 의미에서 안정적 이지 않습니다 . IE의 sort ()는 안정적입니다.


답변

좀 더 연구 한 결과 Mozilla / Firefox의 경우 Array.sort ()가 mergesort를 사용하는 것으로 보입니다. 여기 코드를 참조 하십시오 .


답변

나는 그것이 당신이 참조하는 브라우저 구현에 달려 있다고 생각합니다.

모든 브라우저 유형에는 자체 자바 스크립트 엔진 구현이 있으므로 다릅니다. 다양한 구현에 대해서는 Mozilla 및 Webkit / Khtml의 소스 코드 저장소를 확인할 수 있습니다.

그러나 IE는 비공개 소스이므로 Microsoft에 문의해야 할 수도 있습니다.


답변

V8 v7.0 / Chrome 70부터 V8은 Python의 정렬 알고리즘 인 TimSort를 사용 합니다. Chrome 70은 2018 년 9 월 13 일에 출시되었습니다.

이 변경 사항에 대한 자세한 내용은 V8 dev 블로그의 게시물을 참조하십시오 . 소스 코드 또는 패치 1186801을 읽을 수도 있습니다 .