답변:
이 버그 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를 사용합니다.
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를 사용합니다. 출처
나는 그것이 당신이 참조하는 브라우저 구현에 달려 있다고 생각합니다.
모든 브라우저 유형에는 자체 자바 스크립트 엔진 구현이 있으므로 다릅니다. 다양한 구현에 대해서는 Mozilla 및 Webkit / Khtml의 소스 코드 저장소를 확인할 수 있습니다.
그러나 IE는 비공개 소스이므로 Microsoft에 문의해야 할 수도 있습니다.
V8 v7.0 / Chrome 70부터 V8은 Python의 정렬 알고리즘 인 TimSort를 사용 합니다. Chrome 70은 2018 년 9 월 13 일에 출시되었습니다.
이 변경 사항에 대한 자세한 내용은 V8 dev 블로그의 게시물을 참조하십시오 . 소스 코드 또는 패치 1186801을 읽을 수도 있습니다 .
JavaScript의 Array.sort () 함수에는 배열 요소의 데이터 유형을 기반으로 최상의 정렬 알고리즘 (QuickSort, MergeSort 등)을 선택하는 내부 메커니즘이 있습니다.
빠른 정렬로 시도하십시오.
function sort(arr, compareFn = (a, b) => a <= b) {
if (!arr instanceof Array || arr.length === 0) {
return arr;
}
if (typeof compareFn !== 'function') {
throw new Error('compareFn is not a function!');
}
const partition = (arr, low, high) => {
const pivot = arr[low];
while (low < high) {
while (low < high && compareFn(pivot, arr[high])) {
--high;
}
arr[low] = arr[high];
while (low < high && compareFn(arr[low], pivot)) {
++low;
}
arr[high] = arr[low];
}
arr[low] = pivot;
return low;
};
const quickSort = (arr, low, high) => {
if (low < high) {
let pivot = partition(arr, low, high);
quickSort(arr, low, pivot - 1);
quickSort(arr, pivot + 1, high);
}
return arr;
};
return quickSort(arr, 0, arr.length - 1);
}