javascript常用经典算法详解


Posted in Javascript onJanuary 11, 2017

阅读目录

  • 冒泡排序
  • 插入排序
  • 希尔排序
  • 归并排序
  • 快速排序
  • 选择排序
  • 奇偶排序

总结

前言:在前端大全中看到这句话,以此共勉。基础决定你可能达到的高度, 而业务决定了你的最低瓶颈

其实javascript算法在平时的编码中用处不大,不过不妨碍我们学习它,学习一下这些算法的思想,锻炼一下自己的思维模式。

本文不会每种方法都介绍一下,只介绍一下七种,纯属为了学习而学习,如果觉得代码不是很好理解,可以将数组里面的内容代入函数里面。

不过刚开始理解的时候确实挺头疼的。废话少说,搞起来!!

冒泡排序

原理:

从第一个元素开始,往后比较,遇到比自己小的元素就交换位置

javascript常用经典算法详解

(来源于百度图片)

特点:

交换的次数最多,所以它的性能是最差的

代码实现:

function bubbleSort(arr){
 var len=arr.length;
 for(var i=0;i<len;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;
}
var arr=[2,3,6,4,2,1,90,100,20,5];
console.log(bubbleSort(arr)); // [1, 2, 2, 3, 4, 5, 6, 20, 90, 100]

插入排序

原理:

插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中,从而得到一个新的、个数加一的有序数据

如图所示

javascript常用经典算法详解

在插入排序中,数组会被划分为两种,“有序数组块”和“无序数组块”,

   第一遍的时候从”无序数组块“中提取一个数20作为有序数组块。

   第二遍的时候从”无序数组块“中提取一个数60有序的放到”有序数组块中“,也就是20,60。

   第三遍的时候同理,不同的是发现10比有序数组的值都小,因此20,60位置后移,腾出一个位置让10插入。

   然后按照这种规律就可以全部插入完毕。

下面是一张gif图

javascript常用经典算法详解

特点:

插入算法把要排序的数组分成两部分:

第一部分包含了这个数组的所有元素,但将第一个元素除外(让数组多一个空间才有插入的位置).

第二部分就只包含这一个元素(即待插入元素)。在第一部分排序完成后,再将这个最后元素插入到已排好序的第一部分中

比冒泡排序快一点

代码实现:

//插入排序
//假定当前元素之前的元素已经排好序,先把自己的位置空出来,
//然后前面比自己大的元素依次向后移,直到空出一个"坑",
//然后把目标元素插入"坑"中
function insertSort(arr){
 // 从第二个元素开始,因为要留出一个坑
 for(var i=1;i<arr.length;i++){
 var x=arr[i]; 
 for(var j=i-1;arr[j]>x;j--){ //后挪空出位置 .
  arr[j+1]=arr[j];
 }
 if(arr[j+1]!=x){
  arr[j+1]=x;
 }
 }
 return arr;
}
var arr=[2,3,6,4,2,1,90,100,20,5];
console.log(insertSort(arr,2)); // [1, 2, 2, 3, 4, 5, 6, 20, 90, 100]

希尔排序

原理:

希尔排序也叫 递减增量排序算法,是插入排序的一种神龟进化版。

什么叫递减增量呢,就是定义一个间隔序列,例如是5,3,1。第一次处理,会处理所有间隔为5的,

下一次会处理间隔为3的,最后一次处理间隔为1的元素。也就是相邻元素执行标准插入排序。

 步骤如下:

    1、先取一个小于n的整数d1作为第一个增量,把文件的全部记录分成d1个组。

    2、所有距离为d1的倍数的记录放在同一个组中,在各组内进行直接插入排序。

    3、取第二个增量d2<d1重复上述的分组和排序,

    4、直至所取的增量dt=1(dt<dt-l<…<d2<d1),即所有记录放在同一组中进行直接插入排序为止。

javascript常用经典算法详解

这里增量的取法如下:

    第一次增量的取法为: d=count/2;

    第二次增量的取法为:  d=(count/2)/2;

    最后一直到: d=1;

看上图观测的现象为:

    d=3时:将40跟50比,因50大,不交换。

                 将20跟30比,因30大,不交换。

                 将80跟60比,因60小,交换。

    d=2时:将40跟60比,不交换,拿60跟30比交换,此时交换后的30又比前面的40小,又要将40和30交换,如上图。

                 将20跟50比,不交换,继续将50跟80比,不交换。

    d=1时:这时就是前面讲的插入排序了,不过此时的序列已经差不多有序了,所以给插入排序带来了很大的性能提高。

特点:

 由于多次插入排序,我们知道一次插入排序是稳定的,不会改变相同元素的相对顺序,但在不同的插入排序过程中,

  相同的元素可能在各自的插入排序中移动,最后其稳定性就会被打乱,所以shell排序是不稳定的。

 打个比方,我原来的数组是[5,4,3,2,1]的,这样一打乱就全部重新排了。

代码实现:

function shellSort(arr){
 var gap=Math.floor(arr.length/2);
 while(gap>0){
 for(var i=gap;i<arr.length;i++){
  temp=arr[i];
  for(var j=i;j>=gap&&arr[j-gap]>temp;j-=gap){
  arr[j]=arr[j-gap];
  }
  arr[j]=temp;
 }
 gap=Math.floor(gap/2);
 }
 return arr;
}
var arr = [2,3,6,4,2,1,90,100,20,5];
console.log(shellSort(arr)); //[1, 2, 2, 3, 4, 5, 6, 20, 90, 100]

归并排序

原理:

归并排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。

有以下几个步骤:

  1、把长度为n的输入序列分成两个长度为n/2的子序列;

  2、对这两个子序列继续分为m/2的子序列,一直分下去

  3、将两个排序好的子序列合并成一个最终的排序序列。

javascript常用经典算法详解

再来一张静态图,比较好理解

javascript常用经典算法详解

这里需要补充是,归并中对数组的分割是从上往下的,归并中数组的比较是从下往上的。

特点:

速度仅次于快速排序,为稳定排序算法,一般用于对总体无序,但是各子项相对有序的数列.

属于分治思想,递归归并

代码实现:

/* 排序并合并*/
function merge(left, right) {
 var re = [];
 while(left.length > 0 && right.length > 0) {
 if(left[0] < right[0]) {


// 如果左边的数据小于右边的数据,将左边的数据取出,放到新数组那里
  re.push(left.shift());
 } else {
  re.push(right.shift());
 }
 }
 /* 当左右数组长度不等.将比较完后剩下的数组项链接起来即可 */
 return re.concat(left).concat(right);
}
function mergeSort(arr) {
 if(arr.length == 1){
 return arr;
 }
 /* 首先将无序数组划分为两个数组 */
 var mid = Math.floor(arr.length / 2);
 var left = arr.slice(0, mid);
 var right = arr.slice(mid);
 /* 递归分别对左右两部分数组进行排序合并 */
 return merge(mergeSort(left), mergeSort(right));
}
var arr=[2,3,6,4,2,1,90,100,20,5];
console.log(mergeSort(arr)); // [1, 2, 2, 3, 4, 5, 6, 20, 90, 100]

快速排序

原理:

1、在数据集之中,选择一个元素作为"基准"(pivot)。比如选择下面数字45

javascript常用经典算法详解

2、所有小于"基准"的元素,都移到"基准"的左边;所有大于"基准"的元素,都移到"基准"的右边。

javascript常用经典算法详解

3、对"基准"左边和右边的两个子集,不断重复第一步和第二步,直到所有子集只剩下一个元素为止。

javascript常用经典算法详解

特点:速度最快。和归并排序不同的是,归并排序是先分为两组再继续排,而快速排序是边分边排

代码实现:

// 大致分三步:
 // 1、找基准(一般是以中间项为基准)
 // 2、遍历数组,小于基准的放在left,大于基准的放在right
 // 3、递归
 function quickSort(arr){
 //如果数组<=1,则直接返回
 if(arr.length<=1){
  return arr;
 }
 var pivotIndex=Math.floor(arr.length/2);
 //找基准,并把基准从原数组删除
 var pivot=arr.splice(pivotIndex,1)[0];
 //定义左右数组
 var left=[];
 var right=[];

 //比基准小的放在left,比基准大的放在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));
 }
 var arr=[2,3,6,4,2,1,90,100,20,5];
 console.log(quickSort(arr)); // [1, 2, 2, 3, 4, 5, 6, 20, 90, 100]

选择排序

原理:在要排序的一组数中,选出最小的一个数与第一个位置的数交换,然后剩下的数当中找出最小的与第二个位置的数交换,如此循环直到倒数第二个数和最后一个数为止。

javascript常用经典算法详解

静态图:

javascript常用经典算法详解

特点:可以说是冒泡排序的衍生品,效率比较一般般

代码实现:

// 在无序区中选出最小的元素,然后将它和无序区的第一个元素交换位置。
function selectSort(arr){
 length = arr.length;
 for (var i = 0; i < length; i++){ // 循环数组
 var _min = arr[i]; // 把每一次的 数组里面的数字记录下来
 var k = i;   // 记录下来索引
 for (var j = i + 1; j < length; j++){ // 当前的数字与后一个数字相比较
  if (_min > arr[j]){ //当前的数 大于 后面一个数的话
  _min = arr[j]; // 就讲后面 的数值 保存下来
  k = j;  /// 保存索引
  }
 }
 arr[k] = arr[i]; // 进行交换位置
 arr[i] = _min;
 }
 return arr;
}
var arr=[2,3,6,4,2,1,90,100,20,5];
console.log(selectSort(arr)); // [1, 2, 2, 3, 4, 5, 6, 20, 90, 100]

奇偶排序

原理:

选取所有奇数列的元素与其右侧相邻的元素进行比较,将较小的元素排序在前面;

选取所有偶数列的元素与其右侧相邻的元素进行比较,将较小的元素排序在前面;

重复前面两步,直到所有序列有序为止。

如下图所示:

javascript常用经典算法详解

gif图:

javascript常用经典算法详解

特点:奇数和偶数序列交替比较

代码实现:

function oddEvenSort(arr){
 //swaped用来控制循环是否要继续,如果左边的都比右边的小,则退出循环,返回排好的数组
 var swaped=true; 
 var k=0;
 while(swaped){
 if(k>0){
  swaped=false; 
 }
 for(var i=k;i<arr.length-1;i+=2){
  if(arr[i]>arr[i+1]){
  // 如果左边的数字比右边的大,两者交换位置
  arr[i]=[ arr[i+1], arr[i+1]=arr[i] ][0]; 
  swaped=true;
  }
 }
 k=[1,0][k]; //奇数和偶数之间的转行
 }
 return arr;
} 
var arr=[2,3,6,4,2,1,90,100,20,5];
console.log(oddEvenSort(arr)); // [1, 2, 2, 3, 4, 5, 6, 20, 90, 100]

总结

本文只是总结了算法中的一部分,算法的精髓就在于他们的思想,在js中用处应该不是很大。如果第一遍看不太懂那些代码,可以试着自己敲一遍,我在总结的时候,遇到理解不了的代码,自己敲完理解程度就会加深一些。

理解完,确实这些算法的实现思想博大精深,不得不感慨一下前辈们思想的深度。

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持三水点靠木!

Javascript 相关文章推荐
用JavaScript页面不刷新时全选择,全删除(GridView)
Apr 14 Javascript
JavaScript在IE和Firefox(火狐)的不兼容问题解决方法小结
Apr 13 Javascript
Javascript 遍历页面text控件详解
Jan 06 Javascript
javascript数组去重方法终极总结
Jun 05 Javascript
javascript实现随机读取数组的方法
Aug 03 Javascript
js实现五星评价功能
Mar 08 Javascript
基于JavaScript中字符串的match与replace方法(详解)
Dec 04 Javascript
jQuery获取随机颜色的实例代码
May 21 jQuery
vue中子组件调用兄弟组件方法
Jul 06 Javascript
详解JS中统计函数执行次数与执行时间
Sep 04 Javascript
小程序开发踩坑:页面窗口定位(相对于浏览器定位)(推荐)
Apr 25 Javascript
VUE中V-IF条件判断改变元素的样式操作
Aug 09 Javascript
总结几道关于Node.js的面试问题
Jan 11 #Javascript
微信端开发--登录小程序步骤
Jan 11 #Javascript
Vue数据驱动模拟实现1
Jan 11 #Javascript
利用iscroll4实现轮播图效果实例代码
Jan 11 #Javascript
详解js前端代码异常监控
Jan 11 #Javascript
Vue数据驱动模拟实现3
Jan 11 #Javascript
jQuery实现判断控件是否显示的方法
Jan 11 #Javascript
You might like
使用Xdebug调试和优化PHP程序之[1]
2007/04/17 PHP
php 远程关机操作的代码
2008/12/05 PHP
PHP中如何调用webservice的实例参考
2013/04/25 PHP
PHP的魔术常量__METHOD__简介
2014/07/08 PHP
ThinkPHP中create()方法自动验证实例
2017/04/26 PHP
各种页面定时跳转(倒计时跳转)代码总结
2013/10/24 Javascript
通过复制Table生成word和excel的javascript代码
2014/01/20 Javascript
javascript学习笔记(七)Ajax和Http状态码
2014/10/08 Javascript
JavaScript DOM事件(笔记)
2015/04/08 Javascript
jQuery图片特效插件Revealing实现拉伸放大
2015/04/22 Javascript
jQuery的实例及必知重要的jQuery选择器详解
2016/05/20 Javascript
AngularJS基础 ng-if 指令用法
2016/08/01 Javascript
JS实现的RGB网页颜色在线取色器完整实例
2016/12/21 Javascript
使用Math.max,Math.min获取数组中的最值实例
2017/04/25 Javascript
vue.js在标签属性中插入变量参数的方法
2018/03/06 Javascript
angular 数据绑定之[]和{{}}的区别
2018/09/25 Javascript
详解element-ui表格中勾选checkbox,高亮当前行
2019/09/02 Javascript
[07:08]2014DOTA2西雅图国际邀请赛 小组赛7月11日TOPPLAY
2014/07/11 DOTA
[49:20]VG vs TNC Supermajor小组赛B组败者组决赛 BO3 第二场 6.2
2018/06/03 DOTA
C#返回当前系统所有可用驱动器符号的方法
2015/04/18 Python
python代码 if not x: 和 if x is not None: 和 if not x is None:使用介绍
2016/09/21 Python
Python3利用Dlib19.7实现摄像头人脸识别的方法
2018/05/11 Python
Python实现的redis分布式锁功能示例
2018/05/29 Python
python批量修改图片后缀的方法(png到jpg)
2018/10/25 Python
Python中asyncio模块的深入讲解
2019/06/10 Python
python中count函数简单的实例讲解
2020/02/06 Python
html5页面结构_动力节点Java学院整理
2017/07/10 HTML / CSS
巴西男士胡须和头发护理产品商店:Beard
2017/11/13 全球购物
一个大学生十年的职业规划
2014/01/17 职场文书
音乐教育感言
2014/03/05 职场文书
大学生思想道德自我评价
2015/03/09 职场文书
2015年中秋放假通知范文
2015/08/18 职场文书
详解Spring事件发布与监听机制
2021/06/30 Java/Android
python lambda 表达式形式分析
2022/04/03 Python
CDPR谈《巫师》新作用虚幻5原因 称不会为Epic独占
2022/04/06 其他游戏
html用代码制作虚线框怎么做? dw制作虚线圆圈的技巧
2022/12/24 HTML / CSS