主题
排序算法
交换函数
js
function swap(arr, a, b) {
[arr[b], arr[a]] = [arr[a], arr[b]]
}
冒泡排序
js
function bubbleSort(arr, sort = (a, b) => a - b) {
const 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]) {
swap(arr, j, j + 1)
}
}
}
}
通过第二个参数,控制正序和逆序
js
// 默认从小到大
function bubbleSort(arr, sort = (a, b) => a - b) {
const len = arr.length
for (let i = 0; i < len - 1; i++) {
for (let j = 0; j < len - 1 - i; j++) {
if (sort(arr[j], arr[j + 1]) > 0) {
swap(arr, j, j + 1)
}
}
}
}
bubbleSort(arr, (a, b) => b - a) // 从大到小
选择排序
每一次内循环遍历寻找最小的数,记录下 minIndex
,并在这次内循环结束后交换 minIndex
和 i
的位置
js
function selectionSort(arr) {
const len = arr.length
for (let i = 0; i < len - 1; i++) {
let minIndex = i;
for (let j = i + 1; j < len; j++) {
if (arr[j] < arr[minIndex]) {
minIndex = j;
}
}
swap(arr, i, minIndex);
}
}
插入排序
像玩扑克牌一样,抽到一张牌,往手上已排序的牌堆里放
js
function insertionSort(arr) {
const len = arr.length
for (let i = 1; i < len; i++) {
const temp = arr[i];
let pre = i - 1
while(arr[pre] > temp) {
arr[pre + 1] = arr[pre]
pre--
}
arr[pre + 1] = temp
}
}
希尔排序
js
function shellSort(arr) {
let len = arr.length
let gap = Math.floor(len / 2)
while (gap > 0) {
// 插入排序
for (let i = gap; i < len; i++) {
const temp = arr[i]
let pre = i - gap
while (arr[pre] > temp) {
arr[pre + gap] = arr[pre]
pre -= gap
}
arr[pre + gap] = temp
}
gap = Math.floor(gap / 2)
}
}
归并排序
js
function mergeSort(arr) {
const len = arr.length
if (len < 2) return arr
const min = Math.floor(len / 2)
const left = arr.slice(0, min)
const right = arr.slice(min)
return merge(mergeSort(left), mergeSort(right))
}
function merge(left, right) {
const res = []
while (left.length > 0 && right.length > 0) {
res.push(left[0] <= right[0] ? left.shift() : right.shift())
}
return res.concat(left, right)
}
快速排序
- 从数列中挑出一个元素,称为 "基准"(pivot);
- 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
- 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序;
js
function quickSort(arr, left = 0, right = arr.length - 1) {
if (left < right) {
const point = sort(arr, left, right)
quickSort(arr, left, point - 1)
quickSort(arr, point + 1, right)
}
return arr
}
function sort(arr, left, right) {
// 以 left 为基准值
let index = left + 1 // 可交换的位置
for (let i = index; i <= right; i++) {
if (arr[i] < arr[left]) {
swap(arr, i, index) // index 已交换,即此时 index 位置的就是小于基准值的,所以需要右移一位
index++
}
}
// index - 1 是最后一个小于基准值的,调换 index + 1 和 left
// 则 left 左边都是小于 left 的,右边都是大于 left 的
swap(arr, left, index - 1)
return index - 1 // 把基准值下标返回出去
}