排序算法还是很重要的!!!!
n: 数据规模
k:“桶”的个数
In-place: 占用常数内存,不占用额外内存
Out-place: 占用额外内存
稳定性:排序后2个相等键值的顺序和排序之前它们的顺序相同
冒泡排序
核心就是一趟一趟交换,把大的项换到后面(升序的话)。
// 冒泡排序
function bubbleSort(arr) {
let temp
for(let i=0; i<arr.length; i++) {
for(let j=0; j<arr.length-1-i) {
if(arr[j] > arr[j+1]) {
temp = arr[j]
arr[j] = arr[j+1]
arr[j+1] = temp
}
}
}
return arr
}
特点:最慢的排序算法之一
很明显空间复杂度是O(1)
至于时间复杂度,最好的情况是已经是排好序的,是O(n^2)(可以加一个flag标志,那么最优的时间复杂度是O(n));最差的情况是反序O(n^2);平均时间复杂度是O(n^2)
选择排序
选择排序的核心就是:不断地从无序序列中找到最小元素放到已排序序列的首部,直到所有元素排序完成。
// 选择排序
function selectionSort(arr) {
let min = 0
let minIndex, temp
for(let i=0; i<arr.length-1; i++) {
minIndex = i
for(let j=i+1; j<arr.length; j++) {
if(arr[j] < arr[minIndex]) {
minIndex = j
}
}
temp = arr[minIndex]
arr[minIndex] = arr[i]
arr[i] = temp
}
return arr
}
特点:最稳定的排序算法(时间复杂度永远是O(n^2))
插入排序
原理:扑克的排序方法。依次将未排序的元素插入到已排序的序列中
//插入排序
function insertionSort(arr) {
let temp
for(let i=1; i<arr.length; i++) {
temp = arr[i]
let j = i-1
while(j>=0 && arr[j]>temp) {
arr[j+1] = arr[j]
j--
}
arr[j+1] = temp
}
return arr
}
空间复杂度:O(1)
时间复杂度:最好O(n),最差O(n^2),平均O(n^2)
希尔排序
希尔排序是升级版的插入排序,定义一个间隔进行插入排序,让离正确位置较远的元素尽快回到正确位置。间隔可以i提前定义好的(如701,301,132,57,23,10,4,1),也可以是动态间隔。
//希尔排序
function shellSort(arr) {
let temp
let gap = 1
while(gap < arr.length/3) { //动态定义间隔
gap = gap * 3 + 1
}
for(gap; gap>0; gap=Math.floor(gap/3)) {
for(let i=gap; i<arr.length; i++) {
temp = arr[i]
for(let j=i-gap; j>=0 && arr[j]>temp; j=j-gap) {
arr[j+gap] = arr[j]
}
arr[j+gap] = temp
}
}
return arr
}
空间复杂度: O(1)
时间复杂度:最好是O(nlog n),最差是O(nlog2 n),平均是O(nlog2 n)
归并排序
归并排序使用的分治法,将数组从中点分割成小数组,直到只有一个数,然后反向有序合并,直到合并成一个有序的大数组
// 自上而下递归的归并排序
function mergeSort(arr) {
let len = arr.length
if(len < 2) {
return arr
}
let middleIndex = Math.floor(len/2)
let left = arr.slice(0, middleIndex)
let right = arr.slice(middleIndex, len)
return merge(mergeSort(left), mergeSort(right))
}
//合并两个已排序子序列
function merge(arr1, arr2) {
let result = []
while(arr1.length && arr2.length) {
if(arr1[0] <= arr2[0]) {
result.push(arr1.shift())
} else {
result.push(arr2.shift())
}
}
while(arr1.length) {
result.push(arr1.shift())
}
while(arr2.length) {
result.push(arr2.shift())
}
return result
}
空间复杂度:O(n)
时间复杂度:最快O(nlog n),最差O(nlog n), 平均O(nlog n)
快速排序
快速排序是处理大数据集的最快的排序算法之一,采用分治法。从数组中选一个数作为基点,将小于基点的树放入左边,大于的数放入右边,然后对划分的小数组重复操作,直到排序完成。
//快速排序
function quickSort(arr) {
if(arr.length < 2) {
return arr
}
let privot = arr[0]
let left = []
right = []
for(let i=1; i<arr.length; i++) {
if(arr[i] <= privot) {
left.push(arr[i])
} else {
right.push(arr[i])
}
}
return quickSort(left).concat(privot, quickSort(right))
}
空间复杂度:O(log n)
时间复杂度: 最快O(nlog n),最差O(n^2),平均O(nlog n)