冒泡排序
- 就是从第一个元素开始,重复比较相邻的两个项。若第一项比第二项更大,则交换两者的位置;反之不动
- 时间复杂度:最好
O(n)数组默认就是有序的;最坏O(n^2);平均O(n^2)
// flag 优化思想
// 因为可能 arr 默认就是有序,或者经过最少一次比较之后就有序了
// 所以只要在内循环一次,发现都没有进行换位。就证明 arr 已经有序了
function bubbleSort(arr) {
let len = arr.length
// 外层确保每个元素都和其他进行了一次比较
for (let i = 0
// flag 要在循环内,因为 arr 可能要最少进行一次比较后才有序。在循环内每次重置一下
let flag = false
// 两两比较,完成一次后找出一个最大值
// len - 1 - i 因为每循环一次,就有一个值是确定了大小的,所以下一次就可以忽略它
for (let j = 0
if (arr[j] > arr[j + 1]) {
// 交换两者;es6
flag = true
}
}
if (flag === false) return arr
}
return arr
}
选择排序
- 循环遍历数组,每次都找出当前范围内的最小值(剩下的) ,把它放在当前范围的头部;然后缩小排序范围,继续重复以上操作,直至数组完全有序为止
- 时间复杂度:最好/坏都是
O(n^2),因为内循环都要走只是比较无效并不进行位置替换
function selectSort(arr) {
const len = arr.length
let minIndex = null
for (let i = 0; i < len; i++) {
minIndex = i
for (let j = i; j < len; j++) {
if (arr[minIndex] > arr[j]) {
minIndex = j
}
}
if (minIndex !== i) {
;[arr[i], arr[minIndex]] = [arr[minIndex], arr[i]]
}
}
return arr
}
插入排序
- 当前元素前面的序列是有序的。基于这个前提,从后往前去寻找当前元素在前面那个序列里的正确位置
- 时间复杂度:最好
O(n)数组默认就是有序的;最坏O(n^2);平均O(n^2)
// 取一个数,每次都和他之前内容的进行比较,如果比该值大就往后腾位置
function innerSort(arr) {
const len = arr.length
let temp = null
// i 从 1 开始,因为第一个值本身是有序的 [5]
for (let i = 1
// j用于帮助 temp 寻找自己应该有的定位
let j = i
// 需要 temp 先保存 arr[i],因为后面 arr[j] = arr[j - 1] 会更改 arr[i]
// temp 是需要比较的值,需要找到比它大的值
temp = arr[i]
// 循环比较之前的有序数组,直到找到位置为止
// temp->arr[i]->arr[j]
while (j > 0 && arr[j - 1] > temp) {
// 满足条件就 往后 腾位置
// 前面的值赋值给现在的位置,就是前面的值后移了
arr[j] = arr[j - 1]
// 先移位再改动指针
j--
}
// 找到了位置
arr[j] = temp
}
return arr
}
归并排序
- 将需要被排序的数组从中间分割为二,然后再将分割出来的每个子数组各分割为两半,重复以上操作,直到单个子数组只有一个元素为止。之后从最小的子数组开始,两两合并、确保每次合并出来的数组都是有序的。当合并至原有的规模时,就得到了一个完全排序的数组
function mergeSort(arr) {
const len = arr.length
if (len <= 1) {
return arr
}
const mid = Math.floor(len / 2)
const leftArr = mergeSort(arr.slice(0, mid))
const rightArr = mergeSort(arr.slice(mid, len))
return mergeArr(leftArr, rightArr)
}
function mergeArr(arr1, arr2) {
let i = 0,
j = 0
const len1 = arr1.length
const len2 = arr2.length
let res = []
while (i < len1 && j < len2) {
if (arr1[i] < arr2[j]) {
res.push(arr1[i])
i++
} else {
res.push(arr2[j])
j++
}
}
if (i < len1) {
res = res.concat(arr1.slice(i))
} else {
res = res.concat(arr2.slice(j))
}
return res
}
mergeSort([4, 3, 2, 1])
快速排序
- 会将原始的数组筛选成较小和较大的两个子数组,然后递归地排序两个子数组。具体是先找个一个基准值(二分法),然后遍历它的左右并做处理确保它左边的比它小,右边的比它大。然后按照上面的思路进行分组重复直到子分组为单个时结束
- 时间复杂度:最好
O(nlog(n))数组默认就是有序的;最坏O(n^2);平均O(nlog(n))
function quickSort(arr, left = 0, right = arr.length - 1) {
if(arr.length > 1) {
const lineIndex = partition(arr, left, right)
if(left < lineIndex - 1) {
quickSort(arr, left, lineIndex - 1)
}
if(lineIndex < right) {
quickSort(arr, lineIndex, right)
}
}
return arr
}
function partition(arr, left, right) {
let pivotValue = arr[Math.floor(left + (right-left)/2)]
let i = left
let j = right
while(i<=j) {
while(arr[i] < pivotValue) {
i++
}
while(arr[j] > pivotValue) {
j--
}
if(i<=j) {
swap(arr, i, j)
i++
j--
}
}
return i
}
function swap(arr, i, j) {
[arr[i], arr[j]] = [arr[j], arr[i]]
}