[路飞]_夜见排序JavaScript版

494 阅读2分钟

冒泡排序

一种常见的排序方式;
一种简单易于理解的排序方式;
一种稳定的排序方式;
时间复杂度: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))
};

为什么快速排序快?

利用分治思想,将元素尽可能的与较少的元素相比较找到自己合适的位置