快速排序
核心思想: 选取一个基数,保证左边的数都小于这个基数,右边的数都大于这个基数。然后递归执行上述步骤
时间复杂度 O(nlgn~n^2)
- 最好情况O(nlgn):
在数组中,每次选取的基数都恰好是最数组的
n/2
的位置。
如下图:
- 递归的总次数就等于二叉树的层数(
k
) - 每一层的节点数等于
2^(k-1)
- 二叉树的总节点数等于:
Sn=1+2+4+...+2^(k-1)
=(ak*q-a1)/(q-1)
=2^k-1
设数组一共有 n
个元素,则最少有 2^(k -1 )
个节点,最多有 2^k-1
(其中,k为层数)
因此,总的计算公式为:
总层数: (k=lgn+1
) * 每一层的节点数 (2^(k-1)=n
) = n(lgn+1)
= nlgn
所以,最快的时间复杂度为 O(nlgn)
。
- 最坏情况O(n^2):
最坏的情况就是当每次选中的基数,都位于数组的两边。所以,这就类似于冒泡排序。
let arr = [20, 40, 30, 10, 60, 50]
/**
* 快速排序
* 核心思想: 选取一个基数,保证左边的数都小于这个基数,右边的数都大于这个基数。然后递归执行上述步骤
*/
function quickSort (left = 0, right = 0) {
if (left >= right) return
// 选取基数
let base = arr[left]
let _left = left + 1
let _right = right
// 对比第n趟,左右两边的数
while (_left < _right) {
while (_left <= _right && arr[_left] < base) {
_left++
}
while (_left <= _right && arr[_right] > base) {
_right--
}
if (_left < _right) {
arr[_left] += arr[_right]
arr[_right] = arr[_left] - arr[_right]
arr[_left] = arr[_left] - arr[_right]
}
}
// 以左边_left为交换点,与基准值交换
arr[left] = arr[_right]
arr[_right] = base
// 递归查找左边界
quickSort(left, _right - 1)
// 递归查找右边界
quickSort(_right + 1, right)
}
quickSort(0, arr.length - 1)
console.log('arr', arr)