JavaScript 中常用排序方法的性能对比和分析

一、原生数组排序方法

1. Array.prototype.sort()

javascript

javascript 复制代码
// 默认排序(按字符串Unicode码点)
arr.sort()

// 自定义比较函数
arr.sort((a, b) => a - b) // 数字升序
  • 时间复杂度

    • V8引擎:使用Timsort(归并+插入)

    • 平均/最坏情况:O(n log n)

    • 最佳情况:O(n)

  • 空间复杂度:O(n)(稳定排序需要额外空间)

  • 特点:稳定排序,适合大多数场景


二、经典排序算法实现

2. 快速排序

javascript

复制代码
function quickSort(arr) {
    if (arr.length <= 1) return arr;
    const pivot = arr[Math.floor(arr.length / 2)];
    const left = arr.filter(x => x < pivot);
    const middle = arr.filter(x => x === pivot);
    const right = arr.filter(x => x > pivot);
    return quickSort(left).concat(middle, quickSort(right));
}
  • 平均时间复杂度:O(n log n)

  • 最坏情况:O(n²)(已排序数组)

  • 空间复杂度:O(log n) ~ O(n)

  • 特点:原地排序,不稳定

3. 归并排序

javascript

复制代码
function mergeSort(arr) {
    if (arr.length <= 1) return arr;
    const mid = Math.floor(arr.length / 2);
    return merge(mergeSort(arr.slice(0, mid)), mergeSort(arr.slice(mid)));
}
  • 时间复杂度:O(n log n)

  • 空间复杂度:O(n)

  • 特点:稳定排序,适合链表

4. 堆排序

javascript

复制代码
function heapSort(arr) {
    // 建堆
    for (let i = Math.floor(arr.length / 2) - 1; i >= 0; i--) {
        heapify(arr, arr.length, i);
    }
    // 排序
    for (let i = arr.length - 1; i > 0; i--) {
        [arr[0], arr[i]] = [arr[i], arr[0]];
        heapify(arr, i, 0);
    }
    return arr;
}
  • 时间复杂度:O(n log n)

  • 空间复杂度:O(1)

  • 特点:原地排序,不稳定


三、简单但低效的排序

5. 冒泡排序

javascript

复制代码
function bubbleSort(arr) {
    for (let i = 0; i < arr.length; i++) {
        for (let j = 0; j < arr.length - i - 1; j++) {
            if (arr[j] > arr[j + 1]) {
                [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
            }
        }
    }
    return arr;
}
  • 时间复杂度:O(n²)

  • 特点:实现简单,适合教学


6. 插入排序

javascript

复制代码
function insertionSort(arr) {
    for (let i = 1; i < arr.length; i++) {
        let key = arr[i];
        let j = i - 1;
        while (j >= 0 && arr[j] > key) {
            arr[j + 1] = arr[j];
            j--;
        }
        arr[j + 1] = key;
    }
    return arr;
}
  • 最佳情况:O(n)(已排序)

  • 最坏情况:O(n²)

  • 特点:对小数组或基本有序数组高效


四、性能对比数据

以下是在 Chrome 119 中对 10,000 个随机整数的测试结果:

排序方法 平均时间(ms) 相对速度
原生 sort() 1-3 最快
快速排序 5-10 ≈2-3倍慢
归并排序 8-15 ≈3-5倍慢
堆排序 10-20 ≈4-7倍慢
插入排序 150-300 ≈50-100倍慢
冒泡排序 400-800 ≈150-300倍慢

五、选择建议

1. 日常使用

javascript

javascript 复制代码
// 99% 的场景使用原生 sort
arr.sort((a, b) => a - b);

2. 特殊场景

  • 小数组 (n < 10):插入排序可能更快

  • 几乎有序的数据:插入排序或冒泡排序

  • 内存敏感:堆排序(原地排序)

  • 需要稳定性:归并排序或 Timsort


3. 现代 JavaScript 优化

javascript

javascript 复制代码
// 使用 TypedArray 提高数值排序性能
const float64Array = new Float64Array([3, 1, 2]);
float64Array.sort();  // 使用高度优化的底层实现

// Web Workers 并行处理大数据
if (window.Worker) {
    const worker = new Worker('sort-worker.js');
    worker.postMessage(largeArray);
}

关联阅读推荐

TypedArray 详解


什么是 TypedArray

TypedArray 是 JavaScript 中处理二进制数据的对象,它提供了类似数组的视图来访问原始二进制缓冲区中的数据。

核心特点:
  • 类型化:每个元素都有固定的数据类型(如 Int8、Uint32、Float64 等)

  • 高性能:直接操作内存,避免了 JavaScript 对象的开销

  • 固定长度:创建后长度不可变

  • 内存高效:数据在内存中连续存储

TypedArray 类型
类型 字节长度 数值范围 描述
Int8Array 1 -128 ~ 127 8位有符号整数
Uint8Array 1 0 ~ 255 8位无符号整数
Uint8ClampedArray 1 0 ~ 255 8位无符号整数(限制范围)
Int16Array 2 -32768 ~ 32767 16位有符号整数
Uint16Array 2 0 ~ 65535 16位无符号整数
Int32Array 4 -2³¹ ~ 2³¹-1 32位有符号整数
Uint32Array 4 0 ~ 2³²-1 32位无符号整数
Float32Array 4 ±1.2×10⁻³⁸ ~ ±3.4×10³⁸ 32位浮点数
Float64Array 8 ±5.0×10⁻³²⁴ ~ ±1.8×10³⁰⁸ 64位浮点数
BigInt64Array 8 -2⁶³ ~ 2⁶³-1 64位有符号大整数
BigUint64Array 8 0 ~ 2⁶⁴-1 64位无符号大整数

4. 实际考虑因素

javascript

复制代码
// 根据数据特性选择
function smartSort(arr) {
    if (arr.length < 10) {
        return insertionSort(arr);
    } else if (isAlmostSorted(arr)) {
        return bubbleSort(arr);
    } else {
        return arr.sort((a, b) => a - b);
    }
}

六、最佳实践总结

  1. 优先使用 Array.prototype.sort() - V8 的 Timsort 高度优化

  2. 避免自己实现排序算法 - 除非有特殊需求

  3. 考虑数据特征 - 数据量、有序程度、数据类型

  4. 使用适当的数据结构 - 有时不需要排序,用 Map/Set 更高效

  5. 大数据集考虑分治 - 分批排序或使用 Web Workers


原生 sort() 方法在绝大多数情况下都是最佳选择,除非你有明确的性能瓶颈和特殊需求。


关联阅读推荐

JavaScript 原生 sort() 方法详解

相关推荐
howard20056 小时前
Hive实战任务 - 9.3 实现学生信息排序和统计
hive·排序·汇总·学生信息
伟大的车尔尼3 天前
双指针题目:两个数组的交集
排序·双指针·哈希表
利刃大大5 天前
【JavaSE】十三、枚举类Enum && Lambda表达式 && 列表排序常见写法
java·开发语言·枚举·lambda·排序
波波仔865 天前
clickhouse存储和分区
clickhouse·排序·分区
Tisfy5 天前
LeetCode 3606.优惠券校验器:分类 + 排序
leetcode·题解·排序
2401_841495648 天前
【LeetCode刷题】合并区间
数据结构·python·算法·leetcode·合并·遍历·排序
.YM.Z12 天前
【数据结构】:排序(二)——归并与计数排序详解
数据结构·算法·排序
闻缺陷则喜何志丹2 个月前
【排序】P9127 [USACO23FEB] Equal Sum Subarrays G|普及+
c++·算法·排序·洛谷
少许极端2 个月前
算法奇妙屋(六)-哈希表
java·数据结构·算法·哈希算法·散列表·排序