排序,就是让一组无序数据变成有序的过程。
1、衡量一个排序算法的优劣
- 时间复杂度:具体包括,
最好时间复杂度、最坏时间复杂度以及平均时间复杂度
- 空间复杂度:如果空间复杂度为 1,也叫作原地排序
- 稳定性:排序的稳定性是指相等的数据对象,在排序之后,顺序是否能保证不变
2、常见的排序算法及其思想
1、冒泡排序
- 原理
- 从第一个数据开始,依次比较相邻元素的大小
- 如果前者大于后者,则进行交换操作
- 通过多轮迭代,直到没有交换操作为止
- 性能
- 最好时间复杂度是 O(n):当输入数组刚好是顺序的时候,只需要挨个比较一遍就行了,不需要做交换操作,所以时间复杂度为 O(n)
- 冒泡排序最坏时间复杂度会比较惨,是 O(nn)。也就是说当数组刚好是完全逆序的时候,每轮排序都需要挨个比较 n 次,并且重复 n 次,所以时间复杂度为 O(nn)
- 很显然,当输入数组杂乱无章时,它的平均时间复杂度也是 O(n*n)
- 冒泡排序不需要额外的空间,所以空间复杂度是 O(1)。冒泡排序过程中,当元素相同时不做交换,所以冒泡排序是稳定的排序算法
function bubble( arr ){
let flage = true;
for( let i=0; i<arr.length; i++){
for( let j=0; j<arr.length - 1 -i; j++){
//前一个值大于后一个值时,两个调换位置
if( arr[j] > arr[j+1]){
flage = false;
[arr[j],arr[j+1]] = [arr[j+1],arr[j]]
}
}
if( flage ) break;
}
return arr;
}
var arr=[3,44,38,5,47,15,36,26,27,2,46,4,19,50,48];
bubble(arr)
2、选择排序
- 原理
- 通过多轮迭代,依次找到当前位置应该对应的最小值
function selectSort( arr ){
let len = arr.length;
for( let i=0; i<len; i++ ){
//找到当前位置i对应的最小值所位置所在的index
let index = i;
for( let j=i; j<len; j++ ){
if( arr[index] > arr[j] ){
index = j
}
}
//交换位置
[arr[i],arr[index]] = [arr[index],arr[i]]
}
return arr;
}
var arr=[3,44,38,5,47,15,36,26,27,2,46,4,19,50,48];
selectSort(arr)
3、插叙排序
- 原理
- 利用当前位置的值,依次对比前面的值
- 当前面的值大于当前值时
[j+1] = [j]
- 最终让
[j+1] = temp
function insertSort( arr ){
let len = arr.length;
for( let i=0; i<len; i++ ){
let 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;
}
var arr=[3,44,38,5,47,15,36,26,27,2,46,4,19,50,48];
insertSort(arr)
4、快速排序
function quickSort( arr, left ,right ){
if( left < right ){
let val = arr[right],
i = left - 1;
//当arr[j]小于等于val的值时,调换 arr[i], arr[j]的位置
for( let j=left; j<=right; j++){
if( arr[j] <= val ){
i++;
[ arr[i], arr[j]] = [arr[j],arr[i]]
}
}
//递归调用
quickSort(arr, left, i-1)
quickSort(arr, i+1, right)
}
return arr;
}
var arr=[3,44,38,5,47,15,36,26,27,2,46,4,19,50,48];
quickSort(arr,0,arr.length-1)