1. 冒泡排序、选择排序、插入排序。
它们的平均时间复杂度都为 O(n2)。
1.1 冒泡排序
冒泡排序只会操作相邻的两个数据。
每次冒泡操作都会对相邻的两个元素进行比较,看是否满足大小关系要求。如果不满足就让它俩互换。
一次冒泡会让至少一个元素移动到它应该在的位置,重复 n 次,就完成了 n 个数据的排序工作。
// 冒泡排序
const bubbleSort = arr => {
const length = arr.length;
if (length <= 1) return;
// i < length - 1 是因为外层只需要 length-1 次就排好了,第 length 次比较是多余的。
for (let i = 0; i < length - 1; i++) {
// j < length - i - 1 是因为内层的 length-i-1 到 length-1 的位置已经排好了,不需要再比较一次。
for (let j = 0; j < length - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]
}
}
}
return arr;
};
-
第一,冒泡排序是原地排序算法
-
第二,冒泡排序是稳定的排序算法
-
第三,冒泡排序的时间复杂度是多少 ?
- 最佳情况:T(n) = O(n),当数据已经是正序时。
- 最差情况:T(n) = O(n2),当数据是反序时。
- 平均情况:T(n) = O(n2)。
1.2 插入排序
- 假定第一项已经排序了。
- 后内层循环对当前元素前面有序表进行待插入位置查找,并进行移动。
// 插入排序
const insertionSort = arr => {
const length = arr.length;
if (length <= 1) return;
for (let i = 1; i < length; i++) {
let preIndex = i - 1; //待比较元素的下标(前一个元素下标)
let current = arr[i]; //获取当前元素
while (preIndex >= 0 && arr[preIndex] > current) {
//前置条件之一: 待比较元素比当前元素大
arr[preIndex + 1] = arr[preIndex]; //将待比较元素后移一位
preIndex--; //游标前移一位
}
if (preIndex + 1 != i) {
//避免同一个元素赋值给自身
arr[preIndex + 1] = current; //将当前元素插入预留空位
}
}
return arr;
};
1.3 选择排序
const selectionSort = arr => {
const len = arr.length;
let minIndex, temp;
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;
};
2. 归并排序、快速排序、希尔排序、堆排序
它们的平均时间复杂度都为 O(nlogn)
2.1 归并排序
快排和归并用的都是分治思想 归并排序不是原地排序算法
const mergeSort = (arr) => {
if (arr.length < 2) return arr;
let mid = Math.floor(arr.length / 2);
let left = arr.slice(0, mid);
let right = arr.slice(mid, arr.length);
return merge(mergeSort(left), mergeSort(right))
}
const merge = (left, right) => {
const res = [];
while (left.length && right.length) {
if (left[0] <= right[0]) {
res.push(left.shift())
} else {
res.push(right.shift())
}
}
while (left.length) res.push(left.shift());
while (right.length) res.push(right.shift())
return res;
}
2.2 快速排序
快速排序的特点就是快,而且效率高!它是处理大数据最快的排序算法之一。
快排是原地排序算法。
// 快速排序
const quickSort = arr => {
if (arr.length <= 1) {
return arr;
}
//取基准点
const midIndex = Math.floor(arr.length / 2);
//取基准点的值,splice(index,1) 函数可以返回数组中被删除的那个数 arr[index+1]
const midIndexVal = arr.splice(midIndex, 1);
const left = []; //存放比基准点小的数组
const right = []; //存放比基准点大的数组
//遍历数组,进行判断分配
for (let i = 0; i < arr.length; i++) {
if (arr[i] < midIndexVal) {
left.push(arr[i]); //比基准点小的放在左边数组
} else {
right.push(arr[i]); //比基准点大的放在右边数组
}
}
//递归执行以上操作,对左右两个数组进行操作,直到数组长度为 <= 1
return quickSort(left).concat(midIndexVal, quickSort(right));
};
归并和快排的区别
堆排序和希尔排序 后补。。
https://cloud.tencent.com/developer/article/1475120