JavaScript中的10种排序算法:从入门到精通

作为前端开发者,排序算法是我们必须掌握的基础知识。无论是在面试中,还是在实际开发中处理数据展示时,排序都是一个常见需求。今天,我将用通俗易懂的方式,带你了解JavaScript中最常见的10种排序算法。

1. 冒泡排序 - 最直观的排序方式

冒泡排序可能是最容易理解的排序算法了。它的基本思想是:重复地遍历要排序的数组,一次比较两个元素,如果它们的顺序错误就交换它们。

想象一下水中的气泡,较大的气泡会慢慢浮到水面。在冒泡排序中,较大的元素会"冒泡"到数组的末端。

function bubbleSort(arr) {

const n = arr.length;

for (let i = 0; i < n - 1; i++) {

let swapped = false; // 优化:如果一轮没有交换,说明已经有序

for (let j = 0; j < n - 1 - i; j++) {

if (arr[j] > arr[j + 1]) {

[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]; // ES6解构赋值交换元素

swapped = true;

}

}

if (!swapped) break; // 如果没有发生交换,提前结束

}

return arr;

}

特点:

时间复杂度:最好情况O(n)(已经有序),最坏O(n²)

空间复杂度:O(1)(原地排序)

稳定排序(相等元素不会改变相对位置)

适用场景:数据量小,或者作为学习排序的入门算法。

2. 选择排序 - 每次选择最小的元素

选择排序的思想是:每次从未排序部分选择最小的元素,放到已排序部分的末尾。

function selectionSort(arr) {

const n = arr.length;

for (let i = 0; i < n; i++) {

let minIndex = i; // 假设当前索引是最小值的索引

for (let j = i + 1; j < n; j++) {

if (arr[j] < arr[minIndex]) {

minIndex = j; // 找到更小的值,更新索引

}

}

[arr[i], arr[minIndex]] = [arr[minIndex], arr[i]]; // 交换

}

return arr;

}

特点:

时间复杂度:始终O(n²)

空间复杂度:O(1)

不稳定排序(可能改变相等元素的相对位置)

适用场景:数据量小,且不要求稳定排序的情况。

3. 插入排序 - 扑克牌排序方式

插入排序类似于我们整理扑克牌的方式:将数组分为已排序和未排序两部分,每次从未排序部分取出一个元素,插入到已排序部分的正确位置。

function insertionSort(arr) {

for (let i = 1; i < arr.length; 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;

}

特点:

时间复杂度:最好O(n)(已经有序),最坏O(n²)

空间复杂度:O(1)

稳定排序

适用场景:小规模数据,或者基本有序的数据。

4. 希尔排序 - 插入排序的改进版

希尔排序是插入排序的改进版本,也称为"缩小增量排序"。它通过将原始数组分成若干子序列进行插入排序,然后逐步缩小增量直至整个数组有序。

function shellSort(arr