Який алгоритм Array#sort()
використовує функцію JavaScript ? Я розумію, що для виконання різного роду видів може знадобитися будь-яка аргументація та функції, мене просто цікавить, який алгоритм використовує сорт ванілі.
Який алгоритм Array#sort()
використовує функцію JavaScript ? Я розумію, що для виконання різного роду видів може знадобитися будь-яка аргументація та функції, мене просто цікавить, який алгоритм використовує сорт ванілі.
Відповіді:
Якщо ви подивитеся на цю помилку 224128 , виявиться, що MergeSort використовується Mozilla.
Я щойно подивився на джерело WebKit (Chrome, Safari…) . Залежно від типу масиву використовуються різні методи сортування:
Числові масиви (або масиви примітивного типу) сортуються за допомогою стандартної бібліотечної функції C ++, std::qsort
яка реалізує певну зміну швидкості (як правило, введення ).
Суміжні масиви нечислового типу класифікуються і сортуються за допомогою mergesort, якщо вони доступні (для отримання стабільного сортування) або qsort
якщо сортування об'єднань немає.
Для інших типів (безперервних масивів і, мабуть, для асоціативних масивів) WebKit використовує або виділення сортування (яке вони називають "min" сортування ), або, в деяких випадках, сортує через дерево 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 використовує TimSort, спасибі @celwell. Джерело
Стандарт ECMAscript не визначає, який алгоритм сортування повинен використовуватися. Дійсно, різні браузери мають різні алгоритми сортування. Наприклад, сорт Mozilla / Firefox () не є стабільним (у сортувальному розумінні цього слова) під час сортування карти. Сорт () IE стабільний.
Array.sort
; див. це питання .
Я думаю, що це залежатиме від того, яку реалізацію браузера ви пропонуєте.
Кожен тип браузера має власну реалізацію JavaScript, тому це залежить. Ви можете перевірити репозицію вихідного коду для Mozilla та Webkit / Khtml для різних реалізацій.
Однак IE є закритим джерелом, тому вам, можливо, доведеться запитати когось у Microsoft.
Як і для V8 v7.0 / Chrome 70, V8 використовує TimSort , алгоритм сортування Python. Chrome 70 вийшов 13 вересня 2018 року.
Детальні відомості про цю зміну див. У публікації на блозі V8 Dev . Ви також можете прочитати вихідний код або патч 1186801 .
Функція Array.sort () JavaScript має внутрішні механізми для вибору найкращого алгоритму сортування (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);
}