1、冒泡排序
冒泡排序就是重复“从序列右边开始比较相邻两个数字的大小,再根据结果交换两个数字的位置”这一操作的算法。在这个过程中,数字会像泡泡一样,慢慢“浮”到序列的顶端(或底端),所以这个算法才被称为“冒泡排序”。
const bubbleSort = (arr) => {
const len = arr.length;
for (let i = 0; i < len; i++) {
for (let j = 0; j < len - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
}
}
}
return arr;
};
// 时间复杂度为 O(n^2)。
2、选择排序
选择排序就是重复“从待排序的数据中寻找最小值,将其与序列最左边的数字进行交换”这一操作的算法。在序列中寻找最小值时使用的是线性查找。
const selectSort = (arr) => {
const len = arr.length;
let minIndex;
for (let i = 0; i < len - 1; i++) {
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;
};
// 时间复杂度为 O(n^2)。
3、插入排序
插入排序是一种从序列左端开始依次对数据进行排序的算法。在排序过程中,左侧的数据陆续归位,而右侧留下的就是还未被排序的数据。插入排序的思路就是从右侧的未排序区域内取出一个数据,然后将它插入到已排序区域内合适的位置上。
const insertSort = (arr) => {
const len = arr.length;
let preIndex, curr;
for (let i = 1; i < len; i++) {
preIndex = i - 1;
// 存储当前i的值,后面换位使用
curr = arr[i];
// 当前i值与左侧数据(已排序)比较,直到找到左侧数据(已排序)的元素小于或者等于当前i值的位置
while (preIndex >= 0 && arr[preIndex] > curr) {
arr[preIndex + 1] = arr[preIndex];
preIndex--;
}
arr[preIndex + 1] = curr;
}
return arr;
};
// 时间复杂度为 O(n^2)。
4、快速排序
快速排序算法首先会在序列中随机选择一个基准值(pivot),然后将除了基准值以外的数分为“比基准值小的数”和“比基准值大的数”这两个类别,再将其排列成以下形式。
[ 比基准值小的数 ] 基准值 [ 比基准值大的数 ]
接着,对两个“[ ]”中的数据进行排序之后,整体的排序便完成了。对“[ ]”里面的数据进行排序时同样也会使用快速排序。
const quickSort = (arr) => {
const len = arr.length;
if (len <= 1) {
return arr;
}
const pivotIndex = Math.floor(len / 2);
const pivot = arr.splice(pivotIndex, 1)[0];
const left = [],
right = [];
// splice 使 arr减少一位,故 len - 1
for (let i = 0; i < len - 1; i++) {
if (arr[i] < pivot) {
left.push(arr[i]);
} else {
right.push(arr[i]);
}
}
return quickSort(left).concat([pivot], quickSort(right));
};
// 时间复杂度为 OO(nlogn)。
灵感来自《我的第一本算法书》