「这是我参与2022首次更文挑战的第1天,活动详情查看:2022首次更文挑战」
排序算法
分治:分而治之,先解决子问题,再将子问题的解合并求出原问题
插入排序
- 稳定
- 空间复杂度O(1)
- 时间复杂度O(n^2)
原理
通过比较当前元素和前面的元素,如果大于则进行交换,不断循环直到结束
数组长度10以内,插入排序又快又稳
代码
const insertionSort = function (arr) {
const len = arr.length
for(let i = 1; i < len; i++) {
let curr = arr[i]
let prev = i - 1
while(prev >= 0 && arr[prev] > curr){
arr[prev + 1] = arr[prev--]
}
arr[prev + 1] = curr
}
return arr
}
快速排序
阮一峰
原理
-
通过随机获取中间值
-
在进行循环判断放入左侧的子集还是右侧的子集
-
不断重复,第一步和第二步,直到所有子集只剩最后一个
代码
const quickSort = function(arr) {
if(arr.length < 2) return arr
// 递归的中止条件,也是判断边界值的条件
let index = Math.floor(arr.length >> 1)
// 获取中位数下标
let pivot = arr.splice(index,1)[0]
// 将原数组修改,提取出随机的中位数
let left = []
let right = []
arr.forEach(e => pivot < e ? right.push(e):left.push(e)
// 判断是将e放到左侧还是右侧
return quickSort(left).concat([pivot],quickSort(right))
// 将数组重新拼接,因为是通过pivot作为中间值去判断,所以在拼接的时候左右摆放足以
}
in-place
原理
通过下标不断交换,第一次选择的下标是0
第二次则是通过第一次的选择,搜索对应的区间进行排序
阮一峰老师的则是创建空间分割数组进行排序
代码
const quickSort = function (arr) {
// 交换元素
const swap = function (arr,i,j) {
let temp = arr[i]
arr[i] = arr[j]
arr[j] = temp
}
const partition = function (arr,left,right) {
let pivot = arr[left]
let storeIndex = left
for(let i = left + 1; i <= right; i++) {
if(arr[i] < pivot) {
// 如果每次都是成功判断,数组不会发生变化,如果,中间有间隔,则是真正交换
swap(arr,++storeIndex,i)
}
}
// 将比中位数小的下标和基准数进行交换
swap(arr,left,storeIndex)
// 将所选择坐标向外抛出,给下一次递归使用
return storeIndex
}
const sort = function (arr,left,right){
if (left < right) {
let storeIndex = partition(arr,left,right)
sort(arr,left,storeIndex - 1)
sort(arr,storeIndex + 1,right)
}
}
sort(arr,0,arr.length - 1)
return arr
}
稳定性
快速排序是一个不稳的的排序,因为如果两个数相等,两个数的位置会发生变化,如果是单纯的数组可能变化不大
如果是 [{class:1,name:'hmm'},{class:1,name:'li'}],通过class进行排序这两个对象将被交换
时间复杂度
最好的情况是O(nlogn),最差则是走完所有O(n²)