Array#sort()
Hàm JavaScript sử dụng thuật toán nào ? Tôi hiểu rằng nó có thể sử dụng tất cả các cách lập luận và hàm để thực hiện các loại sắp xếp khác nhau, tôi chỉ đơn giản quan tâm đến thuật toán mà loại vanilla sử dụng.
Array#sort()
Hàm JavaScript sử dụng thuật toán nào ? Tôi hiểu rằng nó có thể sử dụng tất cả các cách lập luận và hàm để thực hiện các loại sắp xếp khác nhau, tôi chỉ đơn giản quan tâm đến thuật toán mà loại vanilla sử dụng.
Câu trả lời:
Nếu bạn nhìn vào lỗi này 224128 , có vẻ như MergeSort đang được Mozilla sử dụng.
Tôi vừa mới có một cái nhìn tại các WebKit (Chrome, Safari ...) nguồn . Tùy thuộc vào loại mảng, các phương pháp sắp xếp khác nhau được sử dụng:
Mảng số (hoặc mảng kiểu nguyên thủy) được sắp xếp bằng hàm thư viện chuẩn C ++ std::qsort
, thực hiện một số biến thể của quicksort (thường là introsort ).
Các mảng liền kề của loại không số được sắp xếp theo chuỗi và được sắp xếp bằng cách sử dụng phép hợp nhất, nếu có (để có được sự sắp xếp ổn định) hoặc qsort
nếu không có sắp xếp hợp nhất.
Đối với các loại khác (mảng không liền kề và có lẽ là cho mảng kết hợp) WebKit sử dụng loại sắp xếp lựa chọn (mà chúng gọi là sắp xếp kiểu min min ) hoặc, trong một số trường hợp, nó sắp xếp thông qua cây AVL. Thật không may, tài liệu ở đây khá mơ hồ nên bạn phải theo dõi các đường dẫn mã để thực sự xem loại phương thức sắp xếp nào được sử dụng.
Và sau đó có những viên đá quý như bình luận này :
// 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).
- Chúng ta chỉ hy vọng rằng bất cứ ai thực sự khắc phục lỗi này, điều này có sự hiểu biết tốt hơn về thời gian chạy không có triệu chứng so với người viết nhận xét này và nhận ra rằng loại radix có mô tả thời gian chạy phức tạp hơn một chút so với O (N).
(Cảm ơn phsource đã chỉ ra lỗi trong câu trả lời ban đầu.)
Không có yêu cầu dự thảo nào cho JS để sử dụng một algorthim sắp xếp cụ thể. Như nhiều người đã đề cập ở đây, Mozilla sử dụng sắp xếp hợp nhất. Tuy nhiên, trong mã nguồn v8 của Chrome, tính đến ngày hôm nay, nó sử dụng QuickSort và InsertsSort, cho các mảng nhỏ hơn.
Từ dòng 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;
}
}
};
Cập nhật Kể từ năm 2018 V8 sử dụng TimSort, cảm ơn @celwell. Nguồn
Tiêu chuẩn ECMAscript không chỉ định thuật toán sắp xếp nào sẽ được sử dụng. Thật vậy, các trình duyệt khác nhau có các thuật toán sắp xếp khác nhau. Ví dụ: sort () của Mozilla / Firefox không ổn định (theo nghĩa sắp xếp của từ) khi sắp xếp bản đồ. Sắp xếp của IE () ổn định.
Array.sort
; thấy câu hỏi này .
Tôi nghĩ rằng điều đó sẽ phụ thuộc vào việc bạn thực hiện trình duyệt nào.
Mỗi loại trình duyệt có triển khai công cụ javascript riêng, do đó, nó phụ thuộc. Bạn có thể kiểm tra repos mã nguồn cho Mozilla và Webkit / Khtml để biết các triển khai khác nhau.
Tuy nhiên IE là nguồn đóng, vì vậy bạn có thể phải hỏi ai đó tại microsoft.
Kể từ V8 v7.0 / Chrome 70, V8 sử dụng TimSort , thuật toán sắp xếp của Python. Chrome 70 được phát hành vào ngày 13 tháng 9 năm 2018.
Xem bài đăng trên blog dev dev để biết chi tiết về sự thay đổi này. Bạn cũng có thể đọc mã nguồn hoặc bản vá 1186801 .
Hàm Array.sort () của JavaScript có các cơ chế bên trong để chọn thuật toán sắp xếp tốt nhất (QuickSort, MergeSort, v.v.) trên cơ sở kiểu dữ liệu của các phần tử mảng.
thử điều này với sắp xếp nhanh chóng:
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);
}