Quale algoritmo utilizza la Array#sort()
funzione JavaScript ? Capisco che possono essere necessari tutti i tipi di argomenti e funzioni per eseguire diversi tipi, sono semplicemente interessato a quale algoritmo viene utilizzato dal tipo vanilla.
Quale algoritmo utilizza la Array#sort()
funzione JavaScript ? Capisco che possono essere necessari tutti i tipi di argomenti e funzioni per eseguire diversi tipi, sono semplicemente interessato a quale algoritmo viene utilizzato dal tipo vanilla.
Risposte:
Se guardi questo bug 224128 , sembra che MergeSort sia utilizzato da Mozilla.
Ho appena dato un'occhiata alla fonte WebKit (Chrome, Safari ...) . A seconda del tipo di array, vengono utilizzati diversi metodi di ordinamento:
Le matrici numeriche (o matrici di tipo primitivo) sono ordinate usando la funzione di libreria standard C ++ std::qsort
che implementa alcune variazioni di quicksort (generalmente introsort ).
Le matrici contigue di tipo non numerico vengono stringite e ordinate utilizzando mergesort, se disponibile (per ottenere un ordinamento stabile) o qsort
se non è disponibile alcun ordinamento di unione.
Per altri tipi (array non contigui e presumibilmente per array associativi) WebKit utilizza un ordinamento di selezione (che chiamano ordinamento "min" ) o, in alcuni casi, ordina tramite un albero AVL. Sfortunatamente, la documentazione qui è piuttosto vaga, quindi dovresti tracciare i percorsi del codice per vedere effettivamente per quali tipi viene utilizzato il metodo di ordinamento.
E poi ci sono gemme come questo commento :
// 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).
- Speriamo solo che chiunque "risolva" effettivamente abbia una migliore comprensione del runtime asintotico rispetto allo scrittore di questo commento e realizzi che l' ordinamento radix ha una descrizione del runtime leggermente più complessa rispetto alla semplice O (N).
(Grazie a phsource per aver segnalato l'errore nella risposta originale.)
Non è richiesto alcun progetto di bozza per JS di utilizzare un algoritmo di ordinamento specifico. Come molti hanno già menzionato qui, Mozilla utilizza il merge sort.Tuttavia, nel codice sorgente v8 di Chrome, ad oggi, utilizza QuickSort e InsertionSort, per array più piccoli.
Dalle linee 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;
}
}
};
Aggiornamento A partire dal 2018 V8 utilizza TimSort, grazie a @celwell. fonte
Lo standard ECMAscript non specifica quale algoritmo di ordinamento deve essere utilizzato. In effetti, diversi browser presentano algoritmi di ordinamento diversi. Ad esempio, l'ordinamento () di Mozilla / Firefox non è stabile (nel senso dell'ordinamento della parola) durante l'ordinamento di una mappa. Sort () di IE è stabile.
Array.sort
; vedi questa domanda .
Penso che dipenderebbe dall'implementazione del browser a cui ti riferisci.
Ogni tipo di browser ha la propria implementazione del motore javascript, quindi dipende. È possibile controllare i repository del codice sorgente per Mozilla e Webkit / Khtml per diverse implementazioni.
IE è comunque chiuso, quindi potrebbe essere necessario chiedere a qualcuno di Microsoft.
A partire da V8 v7.0 / Chrome 70, V8 utilizza TimSort , l'algoritmo di ordinamento di Python. Chrome 70 è stato rilasciato il 13 settembre 2018.
Vedi il post sul blog dev V8 per i dettagli su questa modifica. Puoi anche leggere il codice sorgente o la patch 1186801 .
La funzione Array.sort () di JavaScript ha meccanismi interni per selezionare il miglior algoritmo di ordinamento (QuickSort, MergeSort, ecc.) Sulla base del tipo di dati degli elementi dell'array.
prova questo con ordinamento rapido:
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);
}