快速排序深入分析,包含win快排源码,V8快排源码
function quickSort(arr){
console.log('arr=>'+arr);
if(arr.length<=1){
return arr;
}
var pivotindex=Math.floor(arr.length/2);
var pivot = arr.splice(pivotindex,1)[0];
console.log('pivot=>'.concat(pivot));
var left=[],right=[];
for(var i=0;i<arr.length;i++){
if(arr[i]<pivot){
left.push(arr[i]);
}else{
right.push(arr[i]);
}
}
return quickSort(left).concat([pivot],quickSort(right));
}
console.time('start');
var arr=[3,44,38,5,47,15,36,26,27,2,46,4,19,50,48];
console.log(quickSort(arr));
console.timeEnd('start');
执行循序如下:
arr=>3,44,38,5,47,15,36,26,27,2,46,4,19,50,48
VM439:8 pivot=>26
VM439:2 arr=>3,5,15,2,4,19
VM439:8 pivot=>2
VM439:2 arr=>
VM439:2 arr=>3,5,15,4,19
VM439:8 pivot=>15
VM439:2 arr=>3,5,4
VM439:8 pivot=>5
VM439:2 arr=>3,4
VM439:8 pivot=>4
VM439:2 arr=>3
VM439:2 arr=>
VM439:2 arr=>
VM439:2 arr=>19
VM439:2 arr=>44,38,47,36,27,46,50,48
VM439:8 pivot=>27
VM439:2 arr=>
VM439:2 arr=>44,38,47,36,46,50,48
VM439:8 pivot=>36
VM439:2 arr=>
VM439:2 arr=>44,38,47,46,50,48
VM439:8 pivot=>46
VM439:2 arr=>44,38
VM439:8 pivot=>38
VM439:2 arr=>
VM439:2 arr=>44
VM439:2 arr=>47,50,48
VM439:8 pivot=>50
VM439:2 arr=>47,48
VM439:8 pivot=>48
VM439:2 arr=>47
VM439:2 arr=>
VM439:2 arr=>
VM439:21 [2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50]
VM439:22 start: 9.407ms
int FindPos(double *p,int low,int high){ double val = p[low]; while (low<high) { while(low<high&&p[high]>=val) high--; p[low]=p[high]; while(low<high&&p[low]<val) low++; p[high]=p[low]; } p[low]=val; return low;}void QuickSort(double *a,int low,int high){ if (!a||high<low) return; if (low<high) { int pos=FindPos(a,low,high); QuickSort(a,low,pos-1); QuickSort(a,pos+1,high); }}template <typename T>void QuickSort(T arr[], int n) //快速排序{ QSpartition(arr, 0, n - 1); InsertSort(arr, n); //最后用插入排序对整个数组排序}template <typename T>void QSpartition(T arr[], int low, int high) //快速排序递归函数{ // if (low >= high) //有插入排序,不需要这句// continue; const int min_insert = 128; if (high - low < min_insert) //数据小于一定数量的时候用直接插入排序 { return; //最后用插入排序对整个数组排序 } int i, j; T temp; //下面一段是前中后3个数据进行插入排序 i = (low + high) / 2; if (arr[i] < arr[low]) { temp = arr[i]; arr[i] = arr[low]; arr[low] = temp; } if (arr[high] < arr[i]) { temp = arr[high]; arr[high] = arr[i]; arr[i] = temp; if (arr[i] < arr[low]) { temp = arr[i]; arr[i] = arr[low]; arr[low] = temp; } }// if (high - low < 3) //小区间用插入排序,这里就不需要判断了// return; //不用插入排序,只有2个数据的时候排序错误 temp = arr[i]; arr[i] = arr[low + 1]; //中值放在最左边 i = low + 1; //左右边界缩小1 j = high - 1; //边界2个数字插入排序排过,满足左<=中<=右 while (i < j) { while (temp < arr[j] && i < j) //从右往左扫描小于目标的值,应该放在左半部分 j--; if (i < j) //找到后放在左边 arr[i++] = arr[j]; else break; while (temp > arr[i] && i < j) //从左往右扫描大于目标的值,要放在右边 i++; if (i< j) arr[j--] = arr[i]; else break; } arr[i] = temp; // i = j,正好是分界线,回填目标值 if ((i - low) > 1) QSpartition(arr, low, i - 1); //递归左边 if ((high - i) > 1) QSpartition(arr, i + 1, high); //递归右边}template <typename T>void InsertSort(T arr[], int n) //直接插入排序{ int i, j; T temp; for (i = 1; i < n; i++) { temp = arr[i]; for (j = i - 1; j >= 0; j--) { if (temp < arr[j]) //逐个往前比较,碰到大于目标的,拉过来 arr[j + 1] = arr[j]; else break; } arr[j + 1] = temp; //把目标值填入空位 }}function ArraySort(comparefn) {
// In-place QuickSort algorithm.
// For short (length <= 22) arrays, insertion sort is used for efficiency.
var custom_compare = IS_FUNCTION(comparefn);
function Compare(x,y) {
// Assume the comparefn, if any, is a consistent comparison function.
// If it isn't, we are allowed arbitrary behavior by ECMA 15.4.4.11.
if (x === y) return 0;
if (custom_compare) {
// Don't call directly to avoid exposing the builtin's global object.
return comparefn.call(null, x, y);
}
if (%_IsSmi(x) && %_IsSmi(y)) {
return %SmiLexicographicCompare(x, y);
}
x = ToString(x);
y = ToString(y);
if (x == y) return 0;
else return x < y ? -1 : 1;
};
function InsertionSort(a, from, to) {
for (var i = from + 1; i < to; i++) {
var element = a[i];
// Pre-convert the element to a string for comparison if we know
// it will happen on each compare anyway.
var key =
(custom_compare || %_IsSmi(element)) ? element : ToString(element);
// place element in a[from..i[
// binary search
var min = from;
var max = i;
// The search interval is a[min..max[
while (min < max) {
var mid = min + ((max - min) >> 1);
var order = Compare(a[mid], key);
if (order == 0) {
min = max = mid;
break;
}
if (order < 0) {
min = mid + 1;
} else {
max = mid;
}
}
// place element at position min==max.
for (var j = i; j > min; j--) {
a[j] = a[j - 1];
}
a[min] = element;
}
}
function QuickSort(a, from, to) {
// Insertion sort is faster for short arrays.
if (to - from <= 22) {
InsertionSort(a, from, to);
return;
}
var pivot_index = $floor($random() * (to - from)) + from;
var pivot = a[pivot_index];
// Pre-convert the element to a string for comparison if we know
// it will happen on each compare anyway.
var pivot_key =
(custom_compare || %_IsSmi(pivot)) ? pivot : ToString(pivot);
// Issue 95: Keep the pivot element out of the comparisons to avoid
// infinite recursion if comparefn(pivot, pivot) != 0.
a[pivot_index] = a[from];
a[from] = pivot;
var low_end = from; // Upper bound of the elements lower than pivot.
var high_start = to; // Lower bound of the elements greater than pivot.
// From low_end to i are elements equal to pivot.
// From i to high_start are elements that haven't been compared yet.
for (var i = from + 1; i < high_start; ) {
var element = a[i];
var order = Compare(element, pivot_key);
if (order < 0) {
a[i] = a[low_end];
a[low_end] = element;
i++;
low_end++;
} else if (order > 0) {
high_start--;
a[i] = a[high_start];
a[high_start] = element;
} else { // order == 0
i++;
}
}
QuickSort(a, from, low_end);
QuickSort(a, high_start, to);
}
var old_length = ToUint32(this.length);
if (old_length < 2) return this;
%RemoveArrayHoles(this);
var length = ToUint32(this.length);
// Move undefined elements to the end of the array.
for (var i = 0; i < length; ) {
if (IS_UNDEFINED(this[i])) {
length--;
this[i] = this[length];
this[length] = void 0;
} else {
i++;
}
}
QuickSort(this, 0, length);
// We only changed the length of the this object (in
// RemoveArrayHoles) if it was an array. We are not allowed to set
// the length of the this object if it is not an array because this
// might introduce a new length property.
if (IS_ARRAY(this)) {
this.length = old_length;
}
return this;
}

浙公网安备 33010602011771号