JavaScript手录-排序算法篇
1. 冒泡排序(Bubble Sort)
原理:重复比较相邻元素,将较大的元素逐步"冒泡"到数组末尾。
特点:简单但效率低,适合小规模数据。
function bubbleSort(arr) {const len = arr.length;// 外层循环控制排序轮数for (let i = 0; i < len - 1; i++) {// 内层循环比较相邻元素for (let j = 0; j < len - 1 - i; j++) {if (arr[j] > arr[j + 1]) {// 交换元素[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];}}}return arr;
}
2. 选择排序(Selection Sort)
原理:每次从剩余元素中找到最小(大)值,放到已排序部分的末尾。
特点:不稳定排序,交换次数少,适合数据量小的场景。
function selectionSort(arr) {const len = arr.length;for (let i = 0; i < len - 1; i++) {let minIndex = i; // 记录最小值索引// 寻找剩余元素中的最小值for (let j = i + 1; j < len; j++) {if (arr[j] < arr[minIndex]) {minIndex = j;}}// 交换最小值到当前位置[arr[i], arr[minIndex]] = [arr[minIndex], arr[i]];}return arr;
}
3. 插入排序(Insertion Sort)
原理:将元素逐个插入到已排序部分的正确位置,类似整理扑克牌。
特点:稳定排序,适合近乎有序的数据或小规模数据。
function insertionSort(arr) {const len = arr.length;for (let i = 1; i < len; i++) {let current = arr[i]; // 当前待插入元素let j = i - 1;// 移动已排序元素,为current腾位置while (j >= 0 && arr[j] > current) {arr[j + 1] = arr[j];j--;}// 插入元素arr[j + 1] = current;}return arr;
}
4. 快速排序(Quick Sort)
原理:选择一个"基准值",将数组分为两部分(小于基准和大于基准),递归排序两部分。
特点:高效,平均时间复杂度为 O(n log n),适合大规模数据。
function quickSort(arr) {if (arr.length <= 1) return arr; // 递归终止条件const pivot = arr[0]; // 选择第一个元素作为基准const left = []; // 存放小于基准的元素const right = []; // 存放大于基准的元素// 分割数组for (let i = 1; i < arr.length; i++) {if (arr[i] < pivot) {left.push(arr[i]);} else {right.push(arr[i]);}}// 递归排序并合并结果return [...quickSort(left), pivot, ...quickSort(right)];
}
5. 归并排序(Merge Sort)
原理:将数组不断二分至单个元素,再逐步合并两个有序子数组。
特点:稳定排序,时间复杂度稳定为 O(n log n),但需要额外空间。
// 合并两个有序数组
function merge(left, right) {const result = [];let i = 0, j = 0;// 比较并合并while (i < left.length && j < right.length) {if (left[i] < right[j]) {result.push(left[i++]);} else {result.push(right[j++]);}}// 处理剩余元素return [...result, ...left.slice(i), ...right.slice(j)];
}// 归并排序主函数
function mergeSort(arr) {if (arr.length <= 1) return arr; // 递归终止条件const mid = Math.floor(arr.length / 2);const left = arr.slice(0, mid); // 左半部分const right = arr.slice(mid); // 右半部分// 递归分割并合并return merge(mergeSort(left), mergeSort(right));
}
6. JavaScript 内置排序(Array.sort())
JavaScript 数组自带 sort()
方法,默认将元素转为字符串按 Unicode 顺序排序。实际使用时需传入比较函数:
// 数字升序
const arr = [3, 1, 4, 1, 5];
arr.sort((a, b) => a - b); // [1, 1, 3, 4, 5]// 数字降序
arr.sort((a, b) => b - a); // [5, 4, 3, 1, 1]// 对象排序(按年龄升序)
const users = [{ age: 25 }, { age: 18 }, { age: 30 }];
users.sort((a, b) => a.age - b.age);
注意:sort()
会修改原数组,若需保留原数组可先拷贝:[...arr].sort(...)
。
算法对比总结
算法 | 平均时间复杂度 | 最坏情况 | 稳定性 | 适用场景 |
---|---|---|---|---|
冒泡排序 | O(n²) | O(n²) | 稳定 | 小规模数据 |
选择排序 | O(n²) | O(n²) | 不稳定 | 小规模数据,交换成本高时 |
插入排序 | O(n²) | O(n²) | 稳定 | 近乎有序数据或小规模数据 |
快速排序 | O(n log n) | O(n²) | 不稳定 | 大规模数据,平均性能最优 |
归并排序 | O(n log n) | O(n log n) | 稳定 | 大规模数据,需稳定排序时 |
内置 sort() | 因引擎而异* | 因引擎而异 | 因实现 | 日常开发(需注意比较函数) |