交换排序
冒泡排序
//冒泡排序
let bubbleSort = (arr) => {
for (let i = 0; i < arr.length - 1; i++) {
for (let j = 1; j < arr.length - i; j++) {
if (arr[j] < arr[j - 1]) [arr[j - 1], arr[j]] = [arr[j], arr[j - 1]];
}
}
return arr
}
快排
//快速排序*****递归*****新建地址空间
let quickSort = (arr) => {
if (arr.length < 2) return arr;
let left = [], right = [];
for (let i = 1; i < arr.length; i++) {
if (arr[i] < arr[0]) {
left.push(arr[i])
} else {
right.push(arr[i])
}
}
return [...quickSort(left), arr[0], ...quickSort(right)]
}
//快速排序*****递归*****原地递归
let quickSort = (arr) => {
let help = (arr, left, right) => {
if (left >= right) return arr;
let i = left, j = right, flag = left;
while (i < j) {
while (arr[j] > arr[flag] && j > flag) j--;
if (i >= j) break;
while (arr[i] <= arr[flag] && i < j) i++;
[arr[flag], arr[j], arr[i]] = [arr[j], arr[i], arr[flag]];
flag = i;
}
help(arr, left, flag - 1);
help(arr, flag + 1, right);
return arr
}
return help(arr, 0, arr.length - 1)
}
//快排***非递归*****以后快排都要写成自身排序的形式*****性能最优
let quickSort = (arr) => {
let stack = [[0, arr.length - 1]]
while (stack.length > 0) {
let temp = stack.pop();
if (temp[0] >= temp[1]) continue;
let i = temp[0], j = temp[1], flag = i;
while (i < j) {
while (arr[j] > arr[flag] && j > flag) j--;
if (i >= j) break;
while (arr[i] <= arr[flag] && i < j) i++;
// let temp1 = arr[flag];
// arr[flag] = arr[j];
// arr[j] = arr[i];
// arr[i] = temp1;
//先交换的两个元素先写
[arr[flag], arr[j], arr[i]] = [arr[j], arr[i], arr[flag]];
// [arr[flag], arr[j]] = [arr[j], arr[flag]];
// [arr[i], arr[j]] = [arr[j], arr[i]];
flag = i;
}
stack.push([temp[0], flag - 1]);
stack.push([flag + 1, temp[1]])
}
return arr;
}
插入排序
直接插入排序
//直接插入排序
let insertSort = (arr) => {
for (let i = 1; i < arr.length; i++) {
let temp = arr[i];
let index = i;
for (let j = i - 1; j >= 0 && temp < arr[j]; j--) {
arr[j + 1] = arr[j]
i--;
}
arr[i] = temp;
}
return arr;
}
希尔排序
//希尔排序*****时间复杂度优于O(n^2)
let shellSort = (arr) => {
for (let gap = Math.floor(arr.length / 2); gap > 0; gap = Math.floor(gap / 2)) {
for (let i = gap; i < arr.length; i++) {
let j = i;
let temp = arr[i];
while (j - gap >= 0 && temp < arr[j - gap]) {
arr[j] = arr[j - gap];
j -= gap;
}
arr[j] = temp;
}
}
return arr;
}
选择排序
简单选择排序
//简单选择排序
let selectSort = (arr) => {
for (let i = 0; i < arr.length - 1; i++) {
for (let j = i + 1; j < arr.length; j++) {
if (arr[j] <= arr[i]) [arr[j], arr[i]] = [arr[i], arr[j]];
}
}
return arr;
}
堆排序
//堆排序
const heapSort = (arr, k) => {
let res = [];
//构建堆
let heap = (arr, i) => {
let l = i * 2 + 1, r = i * 2 + 2, smallest = i;
if (l < arr.length && arr[l] < arr[smallest]) smallest = l;
if (r < arr.length && arr[r] < arr[smallest]) smallest = r;
if (smallest !== i) {
[arr[i], arr[smallest]] = [arr[smallest], arr[i]];
heap(arr, smallest);
}
}
//遍历数组构建堆,注意:第一个非叶子节点序号为Math.floor(arr.length / 2) - 1
for (let i = Math.floor(arr.length / 2) - 1; i >= 0; i--) {
heap(arr, i)
}
//将第一个和最后一个元素交换位置,在从新构建堆
for (let i = arr.length - 1; i >= 0; i--) {
[arr[0], arr[i]] = [arr[i], arr[0]];
res.push(arr[i]);
arr.splice(i, 1);
heap(arr, 0);
}
return res
}
归并排序
二路归并排序
// 归并排序
let mergeSort = (arr) => {
let merge = (left, right) => {
let res = [];
let l = r = 0;
while (l < left.length && r < right.length) {
if (left[l] < right[r]) {
res.push(left[l]);
l++;
} else {
res.push(right[r]);
r++;
}
}
while (l < left.length) {
res.push(left[l]);
l++;
}
while (r < right.length) {
res.push(right[r]);
r++;
}
return res;
}
if (arr.length === 1) {
return arr;
}
let mid = Math.floor(arr.length / 2);
let left = arr.slice(0, mid);
let right = arr.slice(mid)
//合并数组
return merge(mergeSort(left), mergeSort(right))
}
时间复杂度和空间复杂度这些老生常谈的东东,先码住。以后有时间再加。
记录记录!