javaScript中常见的排序方法

  之前把常见的那几种算法看了好几次,看的时候也手写了一遍,可是等到过了

好几天又给忘了,所以决定记录下来分享一下,也方便自己以后查看?

冒泡排序

  冒泡排序是属于交换排序的一种,通过比较相邻的两个数据然后进行交

换,冒泡排序的时间复杂度为o(n^2),空间复杂度为o(1)。

function BubbleSort(arr) { 
     for(let i=0;i<arr.length;i++){
         for(let j=0;j<arr.length-i-1;j++){
             if(arr[j]>arr[j+1]){
                 [arr[j],arr[j+1]]=[arr[j+1],arr[j]];  //交换值
             }
         }
     }
     return arr;
  }
选择排序

  选择排序是通过记录下标的方式进行比较的,定义变量(index)等于当前

下标(i),循环当前下标后面的元素,如果后面的元素比当前元素大(或者小),先不着急

交换元素,只替换下标(下标交换),一次循环过后最小元素下标的位置可以确定,最

终交换当前元素(arr[i])值和最小(或最大)下标(arr[index])的值。选择排序的时间复杂

度为o(n^2),空间复杂度为o(1)。

	// 选择
    function chooseSort(arr){
        for(let i = 0;i<arr.length;i++){
           let index = i;  //记录当前元素下标
            for(let j =i+1;j<arr.length;j++){
                if(arr[j]<arr[index]){
                    index = j;  //只交换下标
                }
            }
            [arr[i],arr[index]] = [arr[index],arr[i]]  //一次循环之后再进行交换
        }
        return arr
    }
插入排序

  插入排序默认数组第一个元素有序,从第二个元素开始从后向前进行

比较,插入排序的时间复杂度为o(n^2)。

   //插入排序
    function insert(arr) {
        for (let i = 1; i < arr.length; i++) {
            let current = arr[i];  //记录当前值
            let pre_index = i - 1;  //得到上一个元素下标
            while (current <= arr[pre_index] && pre_index >= 0) {  //如果下标小于0,已经到达数组开头
                arr[pre_index + 1] = arr[pre_index];    //交换元素
                pre_index--;   //再比较下一位元素
            }
            arr[pre_index + 1] = current;
        }
        return arr;
    }

  以上这几种的时间复杂度都是o(n^2),也比较耗费性能。下面介绍两种时间复

杂度为o(nlogn)的排序算法。

快速排序

  我选择了这种方式的快排,比较好理解。还有一种 “刨坑式”的快排,那种在理

解上有点难度,它通过左右两个指针(或变量)对应的值进行比较,然后进行交换。

  以下代码的原理是通过数组进行排序的,递归的去排序左右数组。

    //快排
    function quickSort(arr) {
        if (arr.length <= 1) return arr;
        let left = [],
            middle = [arr[0]],
            right = [];
        for (let index = 1; index < arr.length; index++) {
            if (arr[index] < middle[0]) {
                left.push(arr[index])  //比它小的放到左边
            }else {
                right.push(arr[index])  //本身一样大的元素也放入右边
            }
        }
          // 递归并连接,这一步很重要
        return quickSort(left).concat(middle, quickSort(right))
    }
归并排序

  归并排序主要是利用分治算法的思想,将大问题化解成小问题,最终得到

原问题的解。递归地把数组分割成前后两个子数组直到数组中只有1个元素。同

时,递归地从两个数组中挨个取元素,比较大小并合并。时间复杂度为o(nlogn),空间复杂

度为o(n)。

  // 分割成只有一个元素的数组
function Split(arr){
    if(arr.length<2) return arr;
    let mid = Math.floor(arr.length/2);  //取中间位置
    let left = arr.slice(0,mid);  //得到左边数组
    let right = arr.slice(mid);  //得到右边数组
    return Merge(Split(left),Split(right));
}
function Merge(left,right){
    // 合并+排序
    var result = [];
    var nl = 0;
    var nr =0;
    while(nl<left.length && nr<right.length){
        if(left[nl] < right[nr]){//按从小到大的顺序排列新的组合数组
            result.push(left[nl++]);//扔进去之后迭代
        }else{
            result.push(right[nr++]);
        }
    }
    while(nl<left.length){//剩下的一股脑儿扔进去。
        result.push(left[nl++]);
    }
    while(nr<right.length){
        result.push(right[nr++]);
    }
    return result;
}
基数排序
function radixSort(arr) {
    let max_num = Math.max(...arr);
    max_len = getLengthOfNum(max_num);
    //根据最大数进行循环(确定循环次数)
    for (let digit = 1; digit <= max_len; digit++) {
        let buckets = [];
        for (let i = 0; i < 10; i++) buckets[i] = [];  //定义“桶”
        for (let i = 0; i < arr.length; i++) {
            let value= arr[i];
            let pos = getSpecifiedValue(value, digit);
            buckets[pos ].push(value);
        }
         let result = [];
         buckets.toString().split(',').forEach((val) => {
            if (val) result.push(parseInt(val))
        })
        arr = result;  //改变原数组,再次排序  重要
    }
  return arr;
}
function getLengthOfNum(num) { return (num += '').length }  //得到最大数的长度
//根据对应位置的数,如果不存在,返回0
function getSpecifiedValue(num, position) { return (num += '').split('').reverse().join('')[position - 1] || 0 }

对于基数排序可以参考基数排序详解这篇博客,讲解的比较清晰。

稳定的排序方法:冒泡排序、插入排序、基数排序、归并排序

不稳定的排序方法:快速排序、选择排序、堆排序、希尔排序

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值