排序算法

1、冒泡排序

冒泡排序思想:每一次对比相邻两个数据的大小,小的排在前面,如果前面的数据比后面的大就交换这两个数的位置
   要实现上述规则需要用到两层for循环,外层从第一个数到倒数第二个数,内层从外层的后面一个数到最后一个数。
特点:排序算法的基础。简单实用易于理解,缺点是比较次数多,效率较低。
存在问题:数据的顺序排好之后,冒泡算法仍然会继续进行下一轮的比较,直到arr.length-1次,后面的比较没有意义的。
方案:
    设置标志位flag,如果发生了交换flag设置为true;如果没有交换就设置为false。
    这样当一轮比较结束后如果flag仍为false,即:这一轮没有发生交换,说明数据的顺序已经排好,没有必要继续进行下去。
function bubbleSort(arr) {
        var len= arr.length;
        var temp;//临时变量
        var flag;
        console.time("1.冒泡排序耗时")
        for(var i=0;i<len;i++){
            flag = false;
            for(var j=len-1;j>i;j--){
                if(arr[j]<arr[j-1]){
                    temp = arr[j];
                    arr[j] = arr[j-1];
                    arr[j-1] = temp;
                    flag  = true;
                }
            }
            if(!flag)   //flag = false,没发生交换
                break;
        }
        console.timeEnd("1.冒泡排序耗时");
        return arr;
    }
function bubbleSort2(arr) {
        var low = 0;
        var high= arr.length-1; //设置变量的初始值
        var tmp,j;
        console.time('2.改进后冒泡排序耗时');
        while (low < high) {
            for (j= low; j< high; ++j) {         //正向冒泡,找到最大者
                if (arr[j]> arr[j+1]) {
                    tmp = arr[j]; arr[j]=arr[j+1];arr[j+1]=tmp;
                }
            }
            --high;  //修改high值, 前移一位
            for (j=high; j>low; --j) {          //反向冒泡,找到最小者
                if (arr[j]<arr[j-1]) {
                    tmp = arr[j]; arr[j]=arr[j-1];arr[j-1]=tmp;
                }
            }
            ++low;  //修改low值,后移一位
        }
        console.timeEnd('2.改进后冒泡排序耗时');
        return arr;
    }
//耗时最短
function bubbleSort3(arr) {
        var low = 0;
        var high= arr.length-1; //设置变量的初始值
        var tmp;
        console.time('3.改进后冒泡排序耗时');
        while (low < high) {
            var pos1 = 0,pos2=0;
            for (let i= low; i< high; ++i) { //正向冒泡,找到最大者
                if (arr[i]> arr[i+1]) {
                    tmp = arr[i]; arr[i]=arr[i+1];arr[i+1]=tmp;
                    pos1 = i ;
                }
            }
            high = pos1;// 记录上次位置
            for (let j=high; j>low; --j) { //反向冒泡,找到最小者
                if (arr[j]<arr[j-1]) {
                    tmp = arr[j]; arr[j]=arr[j-1];arr[j-1]=tmp;
                    pos2 = j;
                }
            }

            low = pos2; //修改low值
        }
        console.timeEnd('3.改进后冒泡排序耗时');
        return arr;
    }

2、选择排序

function selectionSort(arr) {
        var len = arr.length;
        var tmp,maxIndex;
        console.time("选择排序耗时")
        for (var i=0;i<len-1;i++){
            maxIndex = i;
            for(var j=i+1;j<len;j++){
                if(arr[j]>arr[maxIndex]) //寻找最大值
                    maxIndex = j;
            }
            if(maxIndex != i){  //若最大值发生变化
                tmp = arr[i];
                arr[i] = arr[maxIndex];
                arr[maxIndex] = tmp;
            }
        }
        console.timeEnd("选择排序耗时");
        return arr;
    }

3、快速排序

思想:快速排序思想:先找到一个基准点(一般指数组的中部),然后数组被该基准点分为两部分,依次与该基准点数据比较,如果比它小,放左边;反之,放右边。左右分别用一个空数组去存储比较后的数据。最后递归执行上述操作,直到数组长度<=1;
特点:快速,常用。缺点是需要另外声明两个数组,浪费了内存空间资源。
function quickSort(arr) {
        if(arr.length<=1){
            return arr;
        }
        var pivotIndex = Math.floor(arr.length/2);  //确定基准位置
        var pivot = arr.splice(pivotIndex,1)[0];    //获取基准值
        var left = [];
        var right = [];
        //console.time("快速排序耗时");
        for (var i=0;i<arr.length;i++){
            if(arr[i]<pivot){
                left.push(arr[i]);
            }else {
                right.push(arr[i]);
            }
        }
        //console.timeEnd("快速排序耗时");
        return quickSort(left).concat([pivot],quickSort(right));
    }
function quickSort1(arr) {

        if(arr.length<=1)
            return arr;

        let left = [];
        let right = [];
        let q = arr[0];
        for(let i=1,l=arr.length;i<l;i++){
            if(arr[i]>q){
                right.push(arr[i]);
            }else{
                left.push(arr[i]);
            }
        }
        return quickSort1(left).concat([q],quickSort1(right));
    }

4、归并排序

作为一种典型的分而治之思想的算法应用,归并排序的实现由两种方法:
自上而下的递归(所有递归的方法都可以用迭代重写,所以就有了第2种方法)
自下而上的迭代
时间复杂度:O(n log n)
//采用自上而下递归
function mergeSort(arr) {
        var len = arr.length;
        if (len<2){
            return arr;
        }

        var middle = Math.floor(len/2),
            left = arr.slice(0,middle),
            right = arr.slice(middle);
        return merge(mergeSort(left),mergeSort(right));
    }

    function merge(left,right) {
        var result = [];

        while (left.length && right.length){
            if (left[0] <= right[0]){
                result.push(left.shift());   //left.shift(),删除数组的第一个元素,并返回该元素
            }else{
                result.push(right.shift());
            }
        }

        while (left.length){
            result.push(left.shift());
        }

        while (right.length){
            result.push(right.shift());
        }

        return result;
    }

5、插入排序

原理:对整个为排序的数列分为两个部分,一部分是已经排序好的,一部分是没有排序好的,每次都从还未排序好的数列中去除一个数,插入到已经排序好的数列之中,直到未排序的数列为零;
在排序过程中,一般默认将数列的第一个数作为已经排序好的数列,将剩余作为未排序好的数列
function insertSort(arr) {
        var len = arr.length;
        var temp,   //存放数组元素
            j;      //索引
        for (var i=1;i<len;i++){
            j = i-1;
            temp = arr[i];
            while (j >= 0 && arr[j] > temp){
                arr[j+1] = arr[j];
                j--;
            }
            arr[j+1] = temp;
        }
        return arr;
    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值