js中sort方法的源码,该怎么解决

JavaScript010

js中sort方法的源码,该怎么解决,第1张

unction 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 + 1i <toi++) {

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 = ij >minj--) {

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 + 1i <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 = 0i <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

}

js提供了sort方法,方便对数组进行排序,然而不同引擎对js的sort方法解析可能存在差异。本文基于v8引擎进行分析。

在v8引擎中,对sort方法提供了2种排序算法:插入排序及快排序。

sort使用方法:

当没有参数传入的时候,其排序顺序默认为,将待排序数据转换为字符串,并按照 Unicode 序列排序;当然,比较函数可以自定义,自定义排序函数需要返回值,其返回值为 -1,0,1 ,分别表示 a<b, a=b, a>b.

当数组长度小于等于10的时候,采用插入排序,大于10的时候,采用快排。

对于长度大于1000的数组,采用的是快排与插入排序混合的方式进行排序的,因为,当数据量很小的时候,插入排序效率优于快排。

快排的平均时间复杂度是nlogn,在排序算法中属于效率最高的。快排是一种不稳定的排序算法,但是一般情况下稳定或者不稳定对我们没有特别大的影响,但是对稳定性要求高的排序,就不能使用快排了。

原文: https://zhuanlan.zhihu.com/p/33626637

sort函数执行时,会依次循环把数组里的两个数传递给函数f,这时候f的参数a和b就分别是传入的两个数,然后分别求出a和b除以2的余数(实际上就是判断a和b是奇数还是偶数,0是偶数,1是奇数)。如果a是偶数,函数f就返回1(或其他任何大于0的数),如果a是奇数且b是偶数就返回-1(或其他任何小于0的数)。sort函数根据f的返回值来对两个数进行排序,如果是大于0的数,就把两个数的值对调,如果是0或小于0的数则不做任何处理。

这样的话,当数组中的所有元素都两两处理完毕后,最终就会形成奇数在前偶数在后的情况了。