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 相关文章推荐
解读IE和firefox下JScript和HREF的执行顺序
Jan 12 Javascript
善用事件代理,警惕闭包的性能陷阱。
Jan 20 Javascript
到处都是jQuery选择器的年代 不了解它们的性能,行吗
Jun 18 Javascript
Jquery插件编写简明教程
Mar 25 Javascript
jQuery插件分享之分页插件jqPagination
Jun 06 Javascript
angularjs基础教程
Dec 25 Javascript
JavaScript按值删除数组元素的方法
Apr 24 Javascript
JavaScript Math.round() 方法
Dec 18 Javascript
深入理解bootstrap框架之入门准备
Oct 09 Javascript
原生js实现节日时间倒计时功能
Jan 18 Javascript
Vue实现点击时间获取时间段查询功能
Aug 21 Javascript
3分钟了解vue数据劫持的原理实现
May 01 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
thinkphp中连接oracle时封装方法无法用的解决办法
2013/06/17 PHP
javascript function、指针及内置对象
2009/02/19 Javascript
使用Jquery来实现可以输入值的下拉选单 雏型
2011/12/06 Javascript
javascript中onmouse事件在div中失效问题的解决方法
2012/01/09 Javascript
Javascript前端UI框架Kit使用指南之kitjs的对话框组件
2014/11/28 Javascript
JQuery日期插件datepicker的使用方法
2016/03/03 Javascript
JavaScript 基础函数_深入剖析变量和作用域
2016/05/18 Javascript
jQuery在ie6下无法设置select选中的解决方法详解
2016/09/20 Javascript
jQuery实现遮罩层登录对话框
2016/12/29 Javascript
vue.js数据绑定的方法(单向、双向和一次性绑定)
2017/07/13 Javascript
JavaScript适配器模式详解
2017/10/19 Javascript
JS改变页面颜色源码分享
2018/02/24 Javascript
在Vue组件中使用 TypeScript的方法
2018/02/28 Javascript
jquery获取select选中值的文本,并赋值给另一个输入框的方法
2018/08/21 jQuery
详解Ubuntu安装angular-cli遇到的坑
2018/09/08 Javascript
layui对工具条进行选择性的显示方法
2019/09/19 Javascript
JavaScript实现密码强度实时验证
2020/03/18 Javascript
原生JS实现留言板
2020/03/26 Javascript
[01:34]2016国际邀请赛中国区预选赛IG战队教练采访
2016/06/27 DOTA
python开发的小球完全弹性碰撞游戏代码
2013/10/15 Python
Python断言assert的用法代码解析
2018/02/03 Python
python读取图片并修改格式与大小的方法
2018/07/24 Python
详解python解压压缩包的五种方法
2019/07/05 Python
Python一键安装全部依赖包的方法
2019/08/12 Python
Python中的xlrd模块使用原理解析
2020/05/21 Python
Keras 中Leaky ReLU等高级激活函数的用法
2020/07/05 Python
python如何遍历指定路径下所有文件(按按照时间区间检索)
2020/09/14 Python
css3翻牌翻数字的示例代码
2020/02/07 HTML / CSS
求职自我评价范文100字
2014/09/23 职场文书
村主任“四风”问题个人对照检查材料思想汇报
2014/10/02 职场文书
领导班子整改措施
2014/10/24 职场文书
2014全年工作总结
2014/11/27 职场文书
2015年小学重阳节活动总结
2015/07/29 职场文书
被委托人身份证明
2015/08/07 职场文书
OpenStack虚拟机快照和增量备份实现方法
2022/04/04 Servers
MySQL 数据 data 基本操作
2022/05/04 MySQL