排序算法
时间复杂度 | 是稳定排序 | 是原地排序 | |
---|---|---|---|
冒泡排序 | O(n²) | 是 | 是 |
插入排序 | O(n²) | 是 | 是 |
选择排序 | O(n²) | 否 | 是 |
快速排序 | O(nlogn) | 否 | 是 |
归并排序 | O(nlogn) | 是 | 否 |
计数排序 | O(n+k)k是数据范围 | 是 | 否 |
桶排序 | O(n) | 是 | 否 |
基数排序 | O(dn)d是维度 | 是 | 否 |
较为通用的排序算法
快速排序
export class QuickSort {
static sort(array: number[]): void {
this.sortInternally(array, 0, array.length - 1)
}
private static sortInternally(array: number[], p: number, r: number) {
if (p >= r) return
// 获取分界点
const q: number = this.partition(array, p, r)
this.sortInternally(array, p, q - 1)
this.sortInternally(array, q + 1, r)
}
private static partition(array: number[], p: number, r: number): number {
/**
* 参考值pivot,小于pivot的放在左边,大于pivot的在右边,最后再把分界点的值和它做交换
* 这样返回的index一定是值在中间的下标
*/
const pivot = array[p]
// 分界点
let index = p + 1
for (let i = index; i <= r; i++) {
if (array[i] < pivot) {
this.swap(array, index, i)
// 找到了比标记值小的元素就移动分界点
index++
}
}
this.swap(array, p, index - 1)
return index - 1
}
private static swap(array: number[], p: number, q: number) {
const temp = array[p]
array[p] = array[q]
array[q] = temp
}
}
优点时间复杂度为O(nlogn),并且是原地排序,内存占用少。可以使用三数取中法或随机数法决定中间点来平衡最差情况的出现
插入排序
sort(array: number[]) {
for (let i = 1; i < array.length; i++) {
let j = i - 1
const temp = array[i]
for (; j >= 0; j--) {
if (array[j] > array[j + 1]) {
array[j + 1] = array[j]
} else {
// 这个说明之前的已经排好了,没必要继续比较
break
}
}
array[j + 1] = temp
}
}
优点稳定排序与原地排序,虽然时间复杂度为O(n²),但是当数据量较小时并不比O(nlogn)慢