Array.prototype.sort 的排序原理以及优缺点
2023-10-05 18:21:36
Array.prototype.sort 的内部原理
Array.prototype.sort() 方法对数组中的元素进行排序,默认情况下按照元素的 Unicode 编码值进行升序排序。但我们也可以通过提供一个比较函数来指定自定义的排序规则。
当我们调用 Array.prototype.sort() 方法时,它会执行以下步骤:
-
如果未提供比较函数,则使用默认的比较函数。默认比较函数将两个元素的 Unicode 编码值进行比较,并返回一个整数:
- 如果第一个元素的 Unicode 编码值小于第二个元素的 Unicode 编码值,则返回 -1。
- 如果第一个元素的 Unicode 编码值等于第二个元素的 Unicode 编码值,则返回 0。
- 如果第一个元素的 Unicode 编码值大于第二个元素的 Unicode 编码值,则返回 1。
-
如果提供了比较函数,则使用该比较函数将两个元素进行比较,并返回一个整数:
- 如果比较函数返回负数,则第一个元素排在第二个元素之前。
- 如果比较函数返回 0,则两个元素的顺序不变。
- 如果比较函数返回正数,则第二个元素排在第一个元素之前。
-
重复步骤 1 或步骤 2,直到数组中的所有元素都已排序。
Array.prototype.sort 所采用的排序算法
Array.prototype.sort() 方法通常使用快速排序算法来对数组进行排序。快速排序是一种分治排序算法,它将数组划分为较小的子数组,然后递归地对每个子数组进行排序,最后将排序后的子数组合并成一个排序后的数组。
快速排序的时间复杂度为 O(n log n)(平均情况)或 O(n^2)(最坏情况),空间复杂度为 O(log n)(平均情况)或 O(n)(最坏情况)。
比较函数的使用方式
我们可以通过提供一个比较函数来指定自定义的排序规则。比较函数是一个函数,它接收两个参数,并返回一个整数:
- 如果第一个元素应该排在第二个元素之前,则返回负数。
- 如果第一个元素应该与第二个元素保持相同顺序,则返回 0。
- 如果第二个元素应该排在第一个元素之前,则返回正数。
例如,以下比较函数将数组中的数字按降序排列:
function compareNumbersDescending(a, b) {
return b - a;
}
const numbers = [1, 3, 2, 5, 4];
numbers.sort(compareNumbersDescending);
console.log(numbers); // [5, 4, 3, 2, 1]
排序的稳定性
Array.prototype.sort() 方法是稳定的,这意味着对于两个相等元素,它们的相对顺序在排序后保持不变。
例如,以下数组包含两个相等元素 "2":
const numbers = [1, 2, 3, 2, 5, 4];
如果我们使用默认的比较函数对数组进行排序,则结果如下:
numbers.sort();
console.log(numbers); // [1, 2, 2, 3, 4, 5]
可以看到,两个相等元素 "2" 保持了它们的相对顺序。
时间复杂度和空间复杂度
Array.prototype.sort() 方法的时间复杂度为 O(n log n)(平均情况)或 O(n^2)(最坏情况),空间复杂度为 O(log n)(平均情况)或 O(n)(最坏情况)。
-
时间复杂度:
- 平均情况下,Array.prototype.sort() 方法的时间复杂度为 O(n log n)。这是因为快速排序算法在平均情况下具有 O(n log n) 的时间复杂度。
- 最坏情况下,Array.prototype.sort() 方法的时间复杂度为 O(n^2)。这是因为当数组已经排序好或逆序时,快速排序算法会退化成冒泡排序,而冒泡排序的时间复杂度为 O(n^2)。
-
空间复杂度:
- 平均情况下,Array.prototype.sort() 方法的空间复杂度为 O(log n)。这是因为快速排序算法在平均情况下具有 O(log n) 的空间复杂度。
- 最坏情况下,Array.prototype.sort() 方法的空间复杂度为 O(n)。这是因为当数组已经排序好或逆序时,快速排序算法会退化成冒泡排序,而冒泡排序的空间复杂度为 O(n)。