javascript如何排序数组_有哪些排序算法

JavaScript数组默认sort()按字符串Unicode排序,非数值排序;需传入(a,b)=>a-b等比较函数实现数值排序,且sort()原地修改数组。

JavaScript 数组默认排序是字符串比较,不是数值排序

调用 Array.prototype.sort() 时不传参数,会把每个元素转成字符串再按 Unicode 码点排序。这意味着 [10, 2, 33, 1] 会变成 [1, 10, 2, 33],因为 "10" 为 true

正确做法是传入比较函数:

const nums = [10, 2, 33, 1];
nums.sort((a, b) => a - b); // 升序 → [1, 2, 10, 33]
nums.sort((a, b) => b - a); // 降序 → [33, 10, 2, 1]
  • 返回负数:a 排在 b 前面
  • 返回 0:a 和 b 位置不变(稳定排序)
  • 返回正数:a 排在 b 后面

注意:sort() 是原地修改,会改变原数组。

手写快速排序时要注意递归边界和 pivot 选择

虽然内置 sort() 在大多数引擎中已优化(V8 用的是 TimSort 变种),但面试或教学中常要求手写快排。常见错误包括:

  • 忘记处理空数组或单元素数组(递归无终止)
  • splice() 分割导致原数组被改,或索引错位
  • arr[0] 当 pivot,在已排序数组上退化为 O(n²)

更稳妥的实现(不修改原数组,随机 pivot):

function quickSort(arr) {
  if (arr.length <= 1) return arr;
  const pivotIndex = Math.floor(Math.random() * arr.length);
  const pivot = arr[pivotIndex];
  const left = [];
  const right = [];
  for (let i = 0; i < arr.length; i++) {
    if (i === pivotIndex) continue;
    if (arr[i] < pivot) left.push(arr[i]);
    else right.push(arr[i]);
  }
  return [...quickSort(left), pivot, ...quickSort(right)];
}

稳定性:内置 sort() 在现代浏览器中是稳定的,但不能依赖旧环境

“稳定”指相等元素的相对顺序不变。比如按对象某个字段排序时,保持原始插入顺序很重要:

const data = [
  { name: 'Alice', score: 85 },
  { name: 'Bob', score: 92 },
  { name: 'Charlie', score: 85 }
];
data.sort((a, b) => a.score - b.score); // 稳定:Alice 始终在 Charlie 前

但 IE 和早期 Safari 的 sort() 不保证稳定。如果需兼容老环境,或对稳定性有强依赖,应手动加次要排序键(如原始索引):

  • 先给数组元素打上 index 字段
  • 比较函数里:若主键相等,再比 a.index - b.index

性能与场景选择:多数情况直接用内置 sort(),别过早优化

自己实现排序算法通常没必要,除非:

  • 需要定制化行为(如并行排序、流式排序、内存受限)
  • 处理超大数据(百万级),且发现 sort() 成为瓶颈(先 profile,别猜)
  • 学习目的或嵌入式 JS 环境(某些精简引擎未完整实现 TimSort)

V8 对 sort() 的实际策略是混合排序:小数组用插入排序,大数组用快排+堆排防最坏,再结合归并保稳定。它比手写快排/归并在真实数据上更鲁棒。

真正容易被忽略的是:浮点数精度、NaN 处理、null/undefined 混排时的隐式转换——这些不会报错,但结果可能不符合直觉。