冒泡排序重复遍历数组,依次比较 2 个元素,如这 2 个元素顺序错误,就交换位置。
function bubbleSort(arr) {
let 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;
}
选择排序时间复杂度 O(n²)
。
function selectSort(arr) {
let len = arr.length
let minIndex = 0
for (let i = 0; i < len; 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
}
插入排序首先构建有序数列,然后在有序数列中从后向前插入未排序元素。
function insertSort(arr) {
let len = arr.length
for (let i = 1; i < len; i++) {
let j = i - 1;
let tmp = arr[i]
while (j >= 0 && arr[j] > tmp) {
arr[j + 1] = arr[j]
j--
}
arr[j + 1] = tmp
}
return arr
}
希尔排序是插入排序的更高效改进版。建立于插入排序的 2 点特性:
希尔排序的步骤。
function shellSort(arr) {
let len = arr.length;
let gap = 1;
while (gap < len / 3) {
gap = gap * 3 + 1;
}
for (; gap > 0; gap = Math.floor(gap / 3)) {
for (let i = gap; i < len; i++) {
let tmp = arr[i];
let j = i - gap;
while (j >= 0 && arr[j] > tmp) {
arr[j + gap] = arr[j];
j -= gap;
}
arr[j + gap] = tmp;
}
}
return arr;
}
归并排序是采用分治法的典型例子。
function mergeSort(arr) {
let len = arr.length
if (len <= 1) {
return arr
}
let middle = len >> 1
let left = arr.slice(0, middle)
let right = arr.slice(middle)
const merge = (left, right) => {
let ret = []
while (left.length && right.length) {
if (left[0] < right[0]) {
ret.push(left.shift())
} else {
ret.push(right.shift())
}
}
while (left.length) {
ret.push(left.shift())
}
while (right.length) {
ret.push(right.shift())
}
return ret
}
return merge(mergeSort(left), mergeSort(right))
}
快速排序采用分治法将 1 个数列分成 2 个子数列进行处理。
function quickSort(arr, left, right) {
if (arr.length <= 1) {
return arr;
}
let pivotIndex = Math.floor(arr.length / 2);
let pivot = arr.splice(pivotIndex, 1)[0];
let left = [];
let right = [];
for (let i = 0; i < arr.length; i++) {
if (arr[i] < pivot) {
left.push(arr[i]);
} else {
right.push(arr[i]);
}
}
return quickSort(left).concat([pivot], quickSort(right));
}