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 相关文章推荐
jQuery 全选效果实现代码
Mar 23 Javascript
javascript 语法基础 想学习js的朋友可以看看
Dec 16 Javascript
信息页文内画中画广告js实现代码(文中加载广告方式)
Jan 03 Javascript
JavaScript实现99乘法表及隔行变色实例代码
Feb 24 Javascript
原生JS实现小小的音乐播放器
Oct 16 Javascript
vue实现商城购物车功能
Nov 27 Javascript
vue2.0 实现页面导航提示引导的方法
Mar 13 Javascript
JS 中可以提升幸福度的小技巧(可以识别更多另类写法)
Jul 28 Javascript
jQuery插件实现的日历功能示例【附源码下载】
Sep 07 jQuery
JS实现页面跳转与刷新的方法汇总
Aug 30 Javascript
详细分析vue响应式原理
Jun 22 Javascript
vue data有值,但是页面{{}} 取不到值的解决
Nov 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
php 设计模式之 工厂模式
2008/12/19 PHP
保存到桌面、设为桌面且带图标的PHP代码
2013/11/19 PHP
ThinkPHP表单自动提交验证实例教程
2014/07/18 PHP
PHP学习笔记(一) 简单了解PHP
2014/08/04 PHP
PHP封装的HttpClient类用法实例
2015/06/17 PHP
php强制用户转向www域名的方法
2015/06/19 PHP
php生成4位数字验证码的实现代码
2015/11/23 PHP
Yii2中cookie用法示例分析
2016/07/18 PHP
PHP+MYSQL实现读写分离简单实战
2017/03/13 PHP
Yii框架 session 数据库存储操作方法示例
2019/11/18 PHP
Input 特殊事件onpopertychange和oninput
2009/06/17 Javascript
Tab页界面,用jQuery及Ajax技术实现
2009/09/21 Javascript
JavaSacript中charCodeAt()方法的使用详解
2015/06/05 Javascript
js实现prototype扩展的方法(字符串,日期,数组扩展)
2016/01/14 Javascript
javascript中Date对象应用之简易日历实现
2016/07/12 Javascript
基于bootstrap的选择框插件icheck
2016/12/23 Javascript
利用JS对iframe父子(内外)页面进行操作的方法教程
2017/06/15 Javascript
JavaScript之class继承_动力节点Java学院整理
2017/07/03 Javascript
vue-router 源码之实现一个简单的 vue-router
2018/07/02 Javascript
JS实现的定时器展示简单秒表、页面弹框及跳转操作完整示例
2020/01/26 Javascript
Vue-router 报错NavigationDuplicated的解决方法
2020/03/31 Javascript
python中实现php的var_dump函数功能
2015/01/21 Python
python 调用pyautogui 实时获取鼠标的位置、移动鼠标的方法
2019/08/27 Python
浅谈在django中使用redirect重定向数据传输的问题
2020/03/13 Python
Python自动发送和收取邮件的方法
2020/08/12 Python
20行Python代码实现一款永久免费PDF编辑工具的实现
2020/08/27 Python
css3弹性盒模型实例介绍
2013/05/27 HTML / CSS
canvas实现滑动验证的实现示例
2020/08/11 HTML / CSS
萨克斯第五大道精品百货店: Saks Fifth Avenue
2017/04/28 全球购物
澳大利亚网上书店:QBD
2021/01/09 全球购物
企业员工培训感言
2014/02/26 职场文书
12.4法制宣传日标语
2014/10/08 职场文书
介绍信怎么写
2015/01/30 职场文书
保洁员岗位职责
2015/02/04 职场文书
世界文化遗产导游词
2019/08/07 职场文书
win11无法登录onedrive错误代码0x8004def7怎么办 ?
2022/04/05 数码科技