【js排序算法】--基础排序算法

前言

前端的代码运行环境本来就不善于处理大量的数据计算,前端也有很多东西比算法重要。那我们为什么要学习算法?

明确学习和使用算法的目的。

一个排序功能,用冒泡排序法,归并排序法,快速排序法?who tm care。一个原生sort函数直接搞定。这就是实用场景,快速实现你的功能即可。

那需不需要学习各种排序算法呢?需要,因为各种排序算法用了很多不用的手段,知识去实现同一个功能,学习里面的知识和优劣对比方法是很有用。

冒泡排序

先了解一下冒泡排序算法,它是最慢的排序算法之一,但也是最容易实现的排序算法。

之所以叫冒泡排序,是因为使用这种排序算法排序的时候,数值会像气泡一样从数组的一端漂浮到另一端。假设要将一组数字按照升序排列,较大的数值会浮动到数组的右侧,而较小的浮动到左侧,之所有有这种现象是因为算法会在数组中多次移动,比较相邻的数据进行换位。

我们先看一个简单的冒泡排序的例子,理解冒泡排序的原理:

// 对下面的字母桉顺序排列
=> E A F D B C
// 第一次排序前两位比较后变成:
=> A E F D B C
// 接着对比二三位比较顺序相同,保持不变,三四位对比互换:
=> A E D F B C
// 然后四五位对比变成
=> A E F B D C
// 最后两位对比互换数据变成:
=> A E F B C D
// 再次循环对比直到所有的顺序都正确
...

算法步骤:

  1. 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
  2. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。
  3. 针对所有的元素重复以上的步骤。
  4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较

在这里插入图片描述

代码实现

// 方法1
function bubbleSort(arr) {
  var len = arr.length;
  for(var i = 0; i < len - 1; i++) {
    for(var j = 0; j < len - 1 - i; j++) {
      if(arr[j] > arr[j+1]) {        // 相邻元素两两对比
        var temp = arr[j+1];        // 元素交换
        arr[j+1] = arr[j];
        arr[j] = temp;
      }
    }
  }
  return arr;
}

// 方法2
function bubblesort(data) {
  var length = data.length;
  for(let outer = length; outer >= 2; --outer) {
    for(let inner = 0; inner < outer - 1; ++inner) {
      if (data[inner] > data[inner + 1]) {
        var temp = data[inner + 1];
        data[inner + 1] = data[inner];
        data[inner] = temp;
      };
    }
  }
  return data;
}

选择排序

选择排序是从数组的开头开始,将第一个元素和其他元素一一对比,检查完所有元素后,将最小的元素放到数组的第一位,然后算法从第二位开始,这个算法一直进行,直到进行到数组的倒数第二个位置时,所有的数据便完成了排序。

以下对五个元素进行选择排序:初始化 E A D H B

// 第一次排序会找到最小值,并将它与列表第一个元素互换
=> A E D H B
// 接着查找第一个元素后面的最小值,并对他们进行互换
=> A B D H E
// D 已经就位,所以下一步对H和E进行互换,列表按顺序排好:
=> A B D E H

在这里插入图片描述

代码实现

function selectionSort(data) {
  let len = data.length;
  let min, temp;
  for(let outer = 0; outer <= len -2; ++outer) {
    min = outer;
    for(let inner = outer + 1; inner <= len - 1; ++inner) {
      if(data[inner] < data[min]) {
        min = inner;
      }
    }
    temp = data[outer];
    data[outer] = data[min];
    data[min] = temp;
  }
}

插入排序

插入排序虽然代码实现没有冒泡排序和选择排序那么简单粗暴,但它的原理却是最容易理解的.玩过扑克牌的同学一下子就明白了,没玩过也不关系,插入排序其实就是最简单直观的排序算法.就好比有一副打乱的扑克牌,现在需要你按照从A到K的顺序排列,我们从杂乱的牌堆里拿出一张,放在桌子左上角,一次再拿出一张,如果比之前的大,我们就直接放在它的右侧,如果小,我们把它放在左侧,后面的依次往右侧移动,就是在合适它当前位置把其他右侧移动,空出一个位置让其插入.

insert

代码实现

 function insertSort(data) {
   let temp, currIndex;
   let len = data.length;
   for(let outer = 1; outer <= len - 1; ++outer) {
     temp = data[outer];
     currIndex = outer;
     while(currIndex > 0 && data[currIndex - 1] >= temp) {
       data[currIndex] = data[currIndex - 1];
       --currIndex;
     }
     data[currIndex] = temp;
   }
 }

这三种排序算法在复杂度上非常相似,从理论上来说他们的执行效率应该差不多,要确定这三种算法的差异,我们可以通过一个非正式的计时来测试他们排序所花费的时间。首先我们需要对一个集合进行排序,100个,1000个,甚至十万百万个元素的集合进行排序,先写一个可以生成集合的类。

function CArray(num) {
  this.dataSource = [];
  this.num = num;
  for(let i = 0; i < num; ++i) {
    this.dataSource[i] = Math.floor(Math.random() * (num + 1)) ;
  }
  return this.dataSource;
}

我们定义好了CArray构造函数,就可以用它生成任意长度的数组,然后用三种不同的排序方法进行排序,统计不同长度元素的数组排序所花时常。来对比这三种排序方法的效率。

 // 1、对数组长度100的数组进行排序
 const arr100 = new CArray(100);

 console.time();
 bubblesort(arr100);
 console.timeEnd();
	
 console.time();
 selectionSort(arr100);
 console.timeEnd();
 
 console.time();
 insertSort(arr100);
 console.timeEnd();
 // default: 0.01318359375 ms
 // default: 0.022705078125 ms
 // default: 0.001953125 ms

很显然没有显著的差异,我们将数组元素换成1000进行排序测试:

 const arr1000 = new CArray(1000);
 // 冒泡排序
 console.time();
 bubblesort(arr1000);
 console.timeEnd();

 console.time();
 selectionSort(arr1000);
 console.timeEnd();
 
 console.time();
 insertSort(arr1000);
 console.timeEnd();
 // default: 1.091064453125 ms 
 // default: 0.604248046875 ms
 // default: 0.0068359375 ms

我们测试将长度换成10000和100000测试:

const arr = new CArray(10000);
 // 冒泡排序
 console.time();
 bubblesort(arr);
 console.timeEnd();

 console.time();
 selectionSort(arr);
 console.timeEnd();
 
 console.time();
 insertSort(arr);
 console.timeEnd();
 // default: 108.0791015625 ms
 // default: 43.179931640625 ms
 // default: 0.046875 ms

// 对100000测试
const arr = new CArray(10000);
 // 冒泡排序
 console.time();
 bubblesort(arr);
 console.timeEnd();

 console.time();
 selectionSort(arr);
 console.timeEnd();
 
 console.time();
 insertSort(arr);
 console.timeEnd();
 // default: 13030.64306640625 ms
 // default: 3983.713134765625 ms
 // default: 0.440185546875 ms

我们对不同长度的数组排序时常测试,得到的结论基本一致,选择排序和插入排序要比冒泡排序快,插入排序是三种排序算法中最快的。不过要记住,这些测试必须要经过多次的运行,最后得到的结果才能算作有效的统计。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

small_Axe

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值