冒泡排序
一种常见的排序方式;
一种简单易于理解的排序方式;
一种稳定的排序方式;
时间复杂度:O(n^2);
特点:稳定
//目标数组
const list = [5,6,3,12,5,2]
const len = list.length;
//遍历目标数组
for(let i = 0 ; i < len ; i++){
// 遍历目标数组,
for(let j = i+1 ; j < len ; j++){
// 将相邻元素中较大元素与较小元素互换
[list[i],list[j]] = [list[j],list[i]]
}
}
console.log(list.join(','))
选择排序
一种简单直观的排序方式
主要原理:
从目标数组中选出数组最小值,最小值放在数组起始位;然后再从剩余的元素中取最小值放入数组第二位;依次类推,直到将目标数组最后一位。完成排序。
时间复杂度:O(n^2)
不是稳定的排序方式
//选择排序
const list = [5,6,3,12,5,2]
const len = list.length;
for(let i = 0 ; i < len ; i++){
let min = list[i];
let idx = i;
for(let j = i+1 ; j < len ; j++){
if(list[j] < min){
min = list[j];
idx = j
}
}
//交换
[ list[i], list[idx]] = [list[idx],list[i]]
}
console.log(list.join(','))
插入排序
跟选择排序类似;从目标数组下标1开始,将当前元素与之前排好序的数组逐一对比;将元素插入排序好的数组对应位置;即为插入排序;
时间复杂度:O(n^2)
插入排序是稳定排序
//获取数组
const list = [5,6,3,12,5,2]
const len = list.length;
//从第一个开始,因为第0个不需要排序
for(let i = 1 ; i < len ; i++){
//拿到第一个数据,是不是要遍历之前的数据;
let j = i-1;
//保存当前数据
const curr = list[i]
while(j>=0 && list[j] > curr){
list[j+1] = list[j];
j--;
}
list[j+1] = curr
}
console.log(list.join(','))
希尔排序
高级的插入排序或者优化版的插入排序;
时间复杂度O(n*logN);
但不是一个稳定的排序;
//依然是获取数组
const list = [5,6,3,12,5,2]
const len = list.length;
//找到分组,通常是数组的一半
let mid = Math.floor(len/2);
//然后循环,将分组的长度组件缩小,比如起始值是10,然后5,2,1,0
while(mid >0){
for(let i = mid ; i < len ; i++){
for(let j = i - mid ; j >=0 && list[j] > list[mid+j] ; j-=mid){
const t = list[j];
list[j] = list[j+mid];
list[j+mid] = t
}
}
mid = Math.floor(mid/2);
}
console.log(list.join(','))
快速排序
主要思路是将目标数组拆分;
将目标数组拆分为两个部分;拆分规则是找数组中任意元素;小于该元素数据放在左侧,大于改元素的数据放在右侧;然后,将划分好的左右侧数据再次按照上述方法拆分;
既然做的是同样的方式,首先想到递归;代码如下:
快排的时间复杂度是:O(n*logN);
因为用到递归,肯定是需要空间的;
所以空间复杂度:O(logN);
但是快速排序不是稳定的排序
异常版本
//快排递归方法
const list = readline().split(',').map(Number);
const loop=(arr)=>{
if(arr.length <=1) return arr;
const p = arr.pop();
const left = [];
const right = []
for(let i = 0 ; i < arr.length ; i++){
if(arr[i] < p){
left.push(arr[i])
}else{
right.push(arr[i])
}
}
//递归
return loop(left).concat(p).concat(loop(right))
};
console.log(loop(list).join(','))
优化后
const loop=(arr)=>{
if(arr.length <=1) return arr;
const p = arr[0];
const left = [];
const right = []
for(let i = 1 ; i < arr.length ; i++){
if(arr[i] < p){
left.push(arr[i])
}else{
right.push(arr[i])
}
}
//递归
return loop(left).concat(p).concat(loop(right))
};
为什么快速排序快?
利用分治思想,将元素尽可能的与较少的元素相比较找到自己合适的位置