经典的排序算法

一、算法概述

算法分类:
常见的排序算法可以分为两大类:

  • 比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此也称为非线性时间比较类排序
  • 非比较类排序:不通过比较来决定元素间的相对次序,它可以突破基于比较排序的时间下界,以线性时间运行,因此也称为线性时间非比较类排序

相关概念:

  • 稳定:如果a刚开始在b的前面,而且a=b,排序之后a仍然在b的前面。
  • 不稳定:如果a原本在b的前面,而且a=b,排序之后a不在b的前面。
  • 时间复杂度:对排序数据的总操作次数,反映当n变化的时候,操作次数呈现什么规律。
  • 空间复杂度:是指算法在计算机中执行所需要的的存储空间的度量,他也是数据规模n的函数

一、arr.sort()

js提供了一种排序方法,sort,sort() 方法用于对数组的元素进行排序。
返回值:对数组的引用。请注意,数组在原数组上进行排序,不生成副本。
传入的参数为一个函数
使用实例:

let arr = [1,2,96,5,63,25,35,35,58,75,94,9,1,38];
console.log(arr,'beforeSort');
//升序
arr.sort((a,b)=>a-b);
console.log(arr,'afterascSort');
//降序
arr.sort((a,b)=>{
   return b-a;
});
console.log(arr,'afterdescSort');

在这里插入图片描述
这里来说一下arr.sort的原理
sort方法可以直接调用,不传入任何参数,也可以传入一个比较函数作为参数,关于比较函数待会再解释,下面先说不传参的时候。

当不传入参数的时候,sort()方法会调用默认的排序的方式,即先调用每个数组项的toString()转型方法,然后按照字符串Unicode编码顺序来对字符串进行排序,例如下面的栗子:

    var arr = [1, 2, 3, 15, 22, 33];
    arr.sort();
    alert(arr);
    //1, 15, 2, 22, 3, 33

输出结果可能和想象中的不一样,但是这是按照这些数字在Unicode字符集中的顺序进行排序的。

那么怎么才能让他按照我们的想法对数组进行排序呢?没错,就是传入一个函数作为参数,来指明排序方式。(注意,参数必须是函数,不能是其他的)

这个函数可以像下面这样写:

function cmp (value1, value2) {
        if (value1 < value2) {
            return 1;
        }
        else if (value1 > value2) {
            return -1;
        } else {
            return 0;
        }
    }

还是解释一下这个函数,如果value2大于value1,那么就会返回1,即true,那么就会执行交换,这样就会把较大的value2放在前面,则较小value1就放在后面。这样整体排下来就会是一个从大到小的排序。
还有一种简化的cmp函数的书写方法:

function cmp (a, b) {
   return b - a;
}

这个函数和上面的函数作用是相同的,当b比较大的时候,就会返回一个大于等于1的数,即true,这样就会执行交换,总体结果也是一种降序排序,可以自己写代码试一下。
以上arr.sort()原理解析借鉴这篇文章:sort解析

二、冒泡排序

冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。

2.1、算法描述(升序)

  • 比较相邻的两个元素,如果第一个比第二个大,交换他们两个的位置;
  • 对每一对相邻的元素进行以上步骤的比较,从开始比较到最后一对,这样在最后的元素应该是最大的数,
  • 针对所有的元素重复以上步骤,除了最后一个;
  • 重复步骤1~3,直到排序完成

2.2、代码实现

代码实现如下:

        function buddleSort(arr){
            var len = arr.length;
            // 一共需要比较n-1轮
            for(let i = 0; i < len-1; i++){
                // 每轮比较都会筛选出一个最大的或者最小的去
                //,所以每比较一轮,就会减少一次
                for(j=0;j<len-i-1;j++){
                    // 如果前面的数大于后边的,交换位置(升序)
                    if(arr[j]>arr[j+1]){
                        let temp = arr[j];
                        arr[j] = arr[j+1];
                        arr[j+1] = temp;
                    }
                }
            }
            return arr;
        }
        console.log(arr,'beforeSort');
        buddleSort(arr);
        console.log(arr,'afterascSort');

在这里插入图片描述

2.3、动图演示

冒泡排序的动图演示如下:
text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQyNjM1NTM5

三、选择排序

选择排序(Selection-sort)是一种简单直观的排序算法。它的工作原理:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。

3.1、算法描述

n个记录的直接选择排序可经过n-1趟直接选择排序得到有序结果。具体算法描述如下:

初始状态:无序区为R[1…n],有序区为空;
第i趟排序(i=1,2,3…n-1)开始时,当前有序区和无序区分别为R[1…i-1]和R(i…n)。该趟排序从当前无序区中-选出关键字最小的记录 R[k],将它与无序区的第1个记录R交换,使R[1…i]和R[i+1…n)分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区;
n-1趟结束,数组有序化了。
每次都会遍历这些个数,假定第一个数为最小的,然后遍历整个数组,将第一个数的下标当做最小值下标,然后与其他数进行比较,如果发现比他小的,将这个更小的数的下标记录下来,当做最小值下标,重复以上步骤最后将最小值放到前面。

3.2、代码实现

代码实现如下:

        function selectSort(arr){
            let len = arr.length;
            let minIndex,temp;
            for(let i = 0; i<len-1;i++){
                minIndex = i;
                for(var j = i+1;j<len;j++){
                    // 寻找最小的数
                    if(arr[j]<arr[minIndex]){
                        minIndex = j;
                    }
                }
                temp = arr[i];
                arr[i] = arr[minIndex];
                arr[minIndex] = temp;
            }
            return arr;
        }
        console.log(arr,'beforeSort');
        selectSort(arr);
        console.log(arr,'afterascSort');

在这里插入图片描述

3.3、动图描述

在这里插入图片描述

四、快速排序

快速排序的基本思想:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。

4.1、算法描述

快速排序使用分治法来把一个串(list)分为两个子串(sub-lists)。具体算法描述如下:

1、从数列中挑出一个元素,称为 “基准”(pivot);

2、重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;

3、递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。

4.2、代码实现

    var quickSort = function(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 = [];

  for (var i = 0; i < arr.length; i++){

    if (arr[i] < pivot) {

      left.push(arr[i]);

    } else {

      right.push(arr[i]);

    }

  }

  return quickSort(left).concat([pivot], quickSort(right));

};

4.3、动图描述

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值