Ответ 1
Если вы посмотрите на эту ошибку 224128, похоже, что MergeSort используется Mozilla.
Какой алгоритм использует функция JavaScript Array#sort()
? Я понимаю, что он может принимать всевозможные аргументы и функции для выполнения разных видов, меня просто интересует, какой алгоритм использует ванильный сорт.
Если вы посмотрите на эту ошибку 224128, похоже, что MergeSort используется Mozilla.
Я только что посмотрел на WebKit (Chrome, Safari...) source. В зависимости от типа массива используются разные методы сортировки:
Числовые массивы (или массивы примитивного типа) сортируются с использованием стандартной библиотечной функции С++ std::qsort
, который реализует некоторые изменения quicksort (обычно introsort).
Смежные массивы нечислового типа строятся и сортируются с использованием mergesort, если доступно (для получения стабильной сортировки) или qsort
if не существует сортировки слияния.
Для других типов (несмежных массивов и предположительно для ассоциативных массивов) 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).
- Позволяет надеяться, что тот, кто на самом деле "исправляет" это, лучше понимает асимптотическое время выполнения, чем писатель этого комментария, и понимает, что sort-sort имеет немного более сложное описание времени выполнения, чем просто 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 использует TimSort, спасибо @celwell. Источник
В стандарте ECMAscript не указывается, какой алгоритм сортировки должен использоваться. Действительно, разные браузеры имеют разные алгоритмы сортировки. Например, при сортировке карты Mozilla/Firefox sort() не сортирует stable (в смысле сортировки слова). IE sort() стабилен.
После еще нескольких исследований для Mozilla/Firefox кажется, что Array.sort() использует mergesort. См. Код здесь.
Я думаю, что это будет зависеть от того, какую версию браузера вы ссылаетесь.
В каждом типе браузера есть собственная реализация движка javascript, так что это зависит. Вы можете проверить исходные коды для Mozilla и Webkit/Khtml для разных реализаций.
IE - закрытый источник, поэтому вам, возможно, придется попросить кого-нибудь в Microsoft.
Начиная с V8 v7.0/Chrome 70, V8 использует TimSort, алгоритм сортировки Python. Chrome 70 был выпущен 13 сентября 2018 года.
См. Сообщение в блоге разработчика V8 для получения подробной информации об этом изменении. Вы также можете прочитать исходный код или патч 1186801.
Функция JavaScript Array.sort() имеет внутренние механизмы для выбора лучшего алгоритма сортировки (QuickSort, MergeSort) на основе типа данных элементов массива.