JS前端面试必备——基本排序算法原理与实现方法详解【插入/选择/归并/冒泡/快速排序】


Posted in Javascript onFebruary 24, 2020

本文实例讲述了JS前端面试必备——基本排序算法原理与实现方法。分享给大家供大家参考,具体如下:

排序算法是面试及笔试中必考点,本文通过动画方式演示,通过实例讲解,最后给出JavaScript版的排序算法

插入排序

JS前端面试必备——基本排序算法原理与实现方法详解【插入/选择/归并/冒泡/快速排序】

算法描述:
1. 从第一个元素开始,该元素可以认为已经被排序
2. 取出下一个元素,在已经排序的元素序列中从后向前扫描
3. 如果该元素(已排序)大于新元素,将该元素移到下一位置
4. 重复步骤 3,直到找到已排序的元素小于或者等于新元素的位置
5. 将新元素插入到该位置后
6. 重复步骤 2~5

现有一组数组 arr = [5, 6, 3, 1, 8, 7, 2, 4]

[5] 6 3 1 8 7 2 4 //第一个元素被认为已经被排序

[5,6] 3 1 8 7 2 4 //6与5比较,放在5的右边

[3,5,6] 1 8 7 2 4 //3与6和5比较,都小,则放入数组头部

[1,3,5,6]  8 7 2 4 //1与3,5,6比较,则放入头部

[1,3,5,6,8]  7 2 4

[1,3,5,6,7,8] 2 4

[1,2,3,5,6,7,8] 4

[1,2,3,4,5,6,7,8]

编程思路:双层循环,外循环控制未排序的元素,内循环控制已排序的元素,将未排序元素设为标杆,与已排序的元素进行比较,小于则交换位置,大于则位置不动

function insertSort(arr){
  var tmp;
  for(var i=1;i<arr.length;i++){
    tmp = arr[i];
    for(var j=i;j>=0;j--){
      if(arr[j-1]>tmp){
        arr[j]=arr[j-1];
      }else{
        arr[j]=tmp;
        break;
      }
    }
  }
  return arr
}

时间复杂度O(n^2)

选择排序

JS前端面试必备——基本排序算法原理与实现方法详解【插入/选择/归并/冒泡/快速排序】

算法描述:直接从待排序数组中选择一个最小(或最大)数字,放入新数组中。

[1] 5 6 3 8 7 2 4 
[1,2] 5 6 3 8 7 4 
[1,2,3] 5 6 8 7 2 4 
[1,2,3,4] 5 6 8 7
[1,2,3,4,5] 6 8 7 
[1,2,3,4,5,6] 8 7 
[1,2,3,4,5,6,7] 8 
[1,2,3,4,5,6,7,8]

编程思路:先假设第一个元素为最小的,然后通过循环找出最小元素,然后同第一个元素交换,接着假设第二个元素,重复上述操作即可

function selectSort(array) {
 var length = array.length,
   i,
   j,
   minIndex,
   minValue,
   temp;
 for (i = 0; i < length - 1; i++) {
  minIndex = i;
  minValue = array[minIndex];
  for (j = i + 1; j < length; j++) {//通过循环选出最小的
   if (array[j] < minValue) {
    minIndex = j;
    minValue = array[minIndex];
   }
  }
  // 交换位置
  temp = array[i];
  array[i] = minValue;
  array[minIndex] = temp;
 }
 return array
}

时间复杂度O(n^2)

归并排序

JS前端面试必备——基本排序算法原理与实现方法详解【插入/选择/归并/冒泡/快速排序】

算法描述:
1. 把 n 个记录看成 n 个长度为 l 的有序子表
2. 进行两两归并使记录关键字有序,得到 n/2 个长度为 2 的有序子表
3. 重复第 2 步直到所有记录归并成一个长度为 n 的有序表为止。

5 6 3 1 8 7 2 4

[5,6] [3,1] [8,7] [2,4]

[5,6] [1,3] [7,8] [2,4]

[5,6,1,3] [7,8,2,4]

[1,3,5,6] [2,4,7,8]

[1,2,3,4,5,6,7,8]

编程思路:将数组一直等分,然后合并

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

 while (left.length && right.length) {
  if (left[0] < right[0])
   tmp.push(left.shift());
  else
   tmp.push(right.shift());
 }

 return tmp.concat(left, right);
}

function mergeSort(a) {
 if (a.length === 1) 
  return a;

 var mid = Math.floor(a.length / 2)
  , left = a.slice(0, mid)
  , right = a.slice(mid);

 return merge(mergeSort(left), mergeSort(right));
}

时间复杂度O(nlogn)

快速排序

JS前端面试必备——基本排序算法原理与实现方法详解【插入/选择/归并/冒泡/快速排序】

算法描述:

  1. 在数据集之中,选择一个元素作为”基准”(pivot)。
  2. 所有小于”基准”的元素,都移到”基准”的左边;所有大于”基准”的元素,都移到”基准”的右边。这个操作称为分区 (partition)操作,分区操作结束后,基准元素所处的位置就是最终排序后它的位置。
  3. 对”基准”左边和右边的两个子集,不断重复第一步和第二步,直到所有子集只剩下一个元素为止。
5 6 3 1 8 7 2 4

pivot
|
5 6 3 1 9 7 2 4
|
storeIndex

5 6 3 1 9 7 2 4//将5同6比较,大于则不更换
|
storeIndex

3 6 5 1 9 7 2 4//将5同3比较,小于则更换
 |
 storeIndex

3 6 1 5 9 7 2 4//将5同1比较,小于则不更换
  |
  storeIndex
...

3 6 1 4 9 7 2 5//将5同4比较,小于则更换
   |
   storeIndex

3 6 1 4 5 7 2 9//将标准元素放到正确位置
   |
storeIndex pivot

上述讲解了分区的过程,然后就是对每个子区进行同样做法

function quickSort(arr){
  if(arr.length<=1) return arr;
  var partitionIndex=Math.floor(arr.length/2);
  var tmp=arr[partitionIndex];
  var left=[];
  var right=[];
  for(var i=0;i<arr.length;i++){
    if(arr[i]<tmp){
      left.push(arr[i])
    }else{
      right.push(arr[i])
    }
  }
  return quickSort(left).concat([tmp],quickSort(right))
}

上述版本会造成堆栈溢出,所以建议使用下面版本

原地分区版:主要区别在于先进行分区处理,将数组分为左小右大

function quickSort(arr){
  function swap(arr,right,left){
    var tmp = arr[right];
    arr[right]=arr[left];
    arr[left]=tmp;
  }
  function partition(arr,left,right){//分区操作,
    var pivotValue=arr[right]//最右面设为标准
    var storeIndex=left;
    for(var i=left;i<right;i++){
      if(arr[i]<=pivotValue){
        swap(arr,storeIndex,i);
        storeIndex++;
      }
    }
    swap(arr,right,storeIndex);
    return storeIndex//返回标杆元素的索引值
  }
  function sort(arr,left,right){
    if(left>right) return;
    var storeIndex=partition(arr,left,right);
    sort(arr,left,storeIndex-1);
    sort(arr,storeIndex+1,right);
  }
  sort(arr,0,arr.length-1);
  return arr;
}

时间复杂度O(nlogn)

冒泡排序

JS前端面试必备——基本排序算法原理与实现方法详解【插入/选择/归并/冒泡/快速排序】

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

5 6 3 1 8 7 2 4

[5 6] 3 1 8 7 2 4 //比较5和6

5 [6 3] 1 8 7 2 4

5 3 [6 1] 8 7 2 4

5 3 1 [6 8] 7 2 4

5 3 1 6 [8 7] 2 4

5 3 1 6 7 [8 2] 4

5 3 1 6 7 2 [8 4]

5 3 1 6 7 2 4 8 // 这样最后一个元素已经在正确位置,所以下一次开始时候就不需要再比较最后一个

编程思路:外循环控制需要比较的元素,比如第一次排序后,最后一个元素就不需要比较了,内循环则负责两两元素比较,将元素放到正确位置上

function bubbleSort(arr){
  var len=arr.length;
  for(var i=len-1;i>0;i--){
    for(var j=0;j<i;j++){
      if(arr[j]>arr[j+1]){
        var tmp = arr[j];
        arr[j]=arr[j+1];
        arr[j+1]=tmp
      }
    }
  }
  return arr;
}

时间复杂度O(n^2)

感兴趣的朋友可以使用在线HTML/CSS/JavaScript代码运行工具:http://tools.3water.com/code/HtmlJsRun测试上述代码运行效果。

Javascript 相关文章推荐
js模拟弹出效果代码修正版
Aug 07 Javascript
JavaScript限定复选框的选择个数示例代码
Aug 25 Javascript
Javascript中常见的校验如域名、手机、邮箱等等
Jan 02 Javascript
jQuery实现的多张图无缝滚动效果【测试可用】
Sep 12 Javascript
vue开发心得和技巧分享
Oct 27 Javascript
使用jquery实现的循环连续可停顿滚动实例
Nov 23 Javascript
JS匿名函数实例分析
Nov 26 Javascript
JS声明式函数与赋值式函数实例分析
Dec 13 Javascript
Angular.js中定时器循环的3种方法总结
Apr 27 Javascript
vuejs选中当前样式active的实例
Aug 22 Javascript
vue element中axios下载文件(后端Python)
May 10 Javascript
VUE 实现动态给对象增加属性,并触发视图更新操作示例
Nov 29 Javascript
Vue快速实现通用表单验证的方法
Feb 24 #Javascript
微信小程序后端实现授权登录
Feb 24 #Javascript
Node使用Nodemailer发送邮件的方法实现
Feb 24 #Javascript
原生javascript实现类似vue的数据绑定功能示例【观察者模式】
Feb 24 #Javascript
Vue 技巧之控制父类的 slot
Feb 24 #Javascript
原生javascript的ajax请求及后台PHP响应操作示例
Feb 24 #Javascript
在 Vue 中编写 SVG 图标组件的方法
Feb 24 #Javascript
You might like
造势之举?韩国总统候选人发布《星际争霸》地图
2017/04/22 星际争霸
PHP 数组和字符串互相转换实现方法
2013/03/26 PHP
php防止SQL注入详解及防范
2013/11/12 PHP
PHP实现ftp上传文件示例
2014/08/21 PHP
Laravel框架数据库CURD操作、连贯操作总结
2014/09/03 PHP
Zend Framework入门教程之Zend_View组件用法示例
2016/12/09 PHP
php删除一个路径下的所有文件夹和文件的方法
2018/02/07 PHP
Laravel框架学习笔记之批量更新数据功能
2019/05/30 PHP
laravel5.1 ajax post 传值_token示例
2019/10/24 PHP
基于jquery的一行代码轻松实现拖动效果
2010/12/28 Javascript
11个用于提高排版水平的基于jquery的文字效果插件
2012/09/14 Javascript
当某个文本框成为焦点时即清除文本框内容
2014/04/28 Javascript
jquery序列化表单以及回调函数的使用示例
2014/07/02 Javascript
JS模式之简单的订阅者和发布者模式完整实例
2015/06/30 Javascript
js变形金刚文字特效代码分享
2015/08/20 Javascript
jquery实现多条件筛选特效代码分享
2015/08/28 Javascript
详解JavaScript的回调函数
2015/11/20 Javascript
原生js配合cookie制作保存路径的拖拽
2015/12/29 Javascript
jQuery 更改checkbox的状态,无效的解决方法
2016/07/22 Javascript
JS滚动到指定位置导航栏固定顶部
2017/07/03 Javascript
js实现类似iphone的网页滑屏解锁功能示例【附源码下载】
2019/06/10 Javascript
小程序登录之支付宝授权的实现示例
2019/12/13 Javascript
vue实现购物车选择功能
2020/01/10 Javascript
windows下安装python paramiko模块的代码
2013/02/10 Python
Python序列之list和tuple常用方法以及注意事项
2015/01/09 Python
使用Python &amp; Flask 实现RESTful Web API的实例
2017/09/19 Python
详解Python3 基本数据类型
2019/04/19 Python
详解用python计算阶乘的几种方法
2019/08/14 Python
关于HTML5 Placeholder新标签低版本浏览器下不兼容的问题分析及解决办法
2016/01/27 HTML / CSS
大学生自我鉴定
2013/12/08 职场文书
企业业务员岗位职责
2014/03/14 职场文书
梅花魂教学反思
2014/04/25 职场文书
我爱幼儿园演讲稿
2014/09/11 职场文书
专业技术职务聘任证明
2015/03/02 职场文书
家庭教育培训学习心得体会
2016/01/14 职场文书
Java 数组内置函数toArray详解
2021/06/28 Java/Android