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 相关文章推荐
解决AJAX中跨域访问出现'没有权限'的错误
Aug 20 Javascript
用JSON做数据传输格式中的一些问题总结
Dec 21 Javascript
深入领悟JavaScript中的面向对象
Nov 18 Javascript
jquery中EasyUI使用技巧小结
Feb 10 Javascript
js实现大转盘抽奖游戏实例
Jun 24 Javascript
js实现的倒计时按钮实例
Jun 24 Javascript
JavaScript实现算术平方根算法-代码超简单
Sep 11 Javascript
简单实现js页面切换功能
Jan 10 Javascript
微信小程序之获取当前位置经纬度以及地图显示详解
May 09 Javascript
AngularJS使用ng-class动态增减class样式的方法示例
May 18 Javascript
Canvas实现微信红包照片效果
Aug 21 Javascript
JavaScript通如何过RGraph实现动态仪表盘
Oct 15 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
php设计模式 Template (模板模式)
2011/06/26 PHP
php中判断文件空目录是否有读写权限的函数代码
2012/08/07 PHP
常见php数据文件缓存类汇总
2014/12/05 PHP
PHP实现阿里大鱼短信验证的实例代码
2017/07/10 PHP
实例讲解PHP表单处理
2019/02/15 PHP
转自Jquery官方 jQuery1.1.3发布,速度提升800%,体积保持20K
2007/08/19 Javascript
一个简单的js树形菜单
2011/12/09 Javascript
详解强大的jQuery选择器之基本选择器、层次选择器
2012/02/07 Javascript
JavaScript 反科里化 this [译]
2012/09/20 Javascript
禁止选中文字兼容IE、Chrome、FF等
2013/09/04 Javascript
判断在css加载完毕后执行后续代码示例
2014/09/03 Javascript
JavaScript基础语法、dom操作树及document对象
2014/12/02 Javascript
js实现用户注册协议倒计时的方法
2015/01/21 Javascript
如何实现移动端浏览器不显示 pc 端的广告
2015/10/15 Javascript
Angular ui.bootstrap.pagination分页
2017/01/20 Javascript
基于Vue.js 2.0实现百度搜索框效果
2020/12/28 Javascript
详解vue中localStorage的使用方法
2018/11/22 Javascript
微信小程序学习笔记之表单提交与PHP后台数据交互处理图文详解
2019/03/28 Javascript
前端插件之Bootstrap Dual Listbox使用教程
2019/07/23 Javascript
简单了解JavaScript sort方法
2019/11/25 Javascript
React实现todolist功能
2020/12/28 Javascript
python基础教程之常用运算符
2014/08/29 Python
python实现机器学习之元线性回归
2018/09/06 Python
利用Django提供的ModelForm增删改数据的方法
2019/01/06 Python
Python基础之函数原理与应用实例详解
2020/01/03 Python
pytorch实现MNIST手写体识别
2020/02/14 Python
购买大码女装:Lane Bryant
2016/09/07 全球购物
美国购买汽车零件网站:Buy Auto Parts
2018/04/02 全球购物
澳大利亚排名第一的狂热牛仔品牌:ONETEASPOON
2018/11/20 全球购物
Vuori官网:运动服装的终级表现
2021/01/27 全球购物
西部世纪面试题
2014/12/05 面试题
互联网创业计划书的书写步骤
2014/01/28 职场文书
幼儿园中班区域活动总结
2014/07/09 职场文书
2015教师年度考核评语
2015/03/25 职场文书
预备党员转正意见
2015/06/01 职场文书
Python Django项目和应用的创建详解
2021/11/27 Python