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 相关文章推荐
Google Suggest ;-) 基于js的动态下拉菜单
Oct 11 Javascript
js判断输入是否为正整数、浮点数等数字的函数代码
Nov 17 Javascript
Jquery动态更改一张位图的src与Attr的使用
Jul 31 Javascript
JQuery 传送中文乱码问题的简单解决办法
May 24 Javascript
js操作数据库实现注册和登陆的简单实例
May 26 Javascript
判断输入的字符串是否是日期格式的简单方法
Jul 11 Javascript
AngularJs Understanding the Model Component
Sep 02 Javascript
JavaScript中如何使用cookie实现记住密码功能及cookie相关函数介绍
Nov 10 Javascript
vue动画之点击按钮往上渐渐显示出来的实例
Sep 29 Javascript
对vue v-if v-else-if v-else 的简单使用详解
Sep 29 Javascript
JS二级菜单不同实现方法分析【4种方法】
Dec 21 Javascript
vue实现短信验证码登录功能(流程详解)
Dec 10 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指定函数参数默认值示例代码
2013/12/04 PHP
laravel实现查询最后执行的一条sql语句的方法
2019/10/09 PHP
JavaScript 私有成员分析
2009/01/13 Javascript
JavaScript高级程序设计 读书笔记之八 Function类及闭包
2012/02/27 Javascript
JS获取几种URL地址的方法小结
2014/02/26 Javascript
jquery简单实现图片切换效果的方法
2015/05/12 Javascript
javascript实现根据iphone屏幕方向调用不同样式表的方法
2015/07/13 Javascript
jQuery.cookie.js使用方法及相关参数解释
2017/03/06 Javascript
浅谈Node Inspector 代理实现
2017/10/19 Javascript
全面介绍vue 全家桶和项目实例
2017/12/27 Javascript
微信小程序ibeacon三点定位详解
2018/10/31 Javascript
vue中使用WX-JSSDK的两种方法(推荐)
2020/01/18 Javascript
微信小程序中的列表切换功能实例代码详解
2020/06/09 Javascript
深入了解JavaScript词法作用域
2020/07/29 Javascript
Bootstrap FileInput实现图片上传功能
2021/01/28 Javascript
浅谈python抛出异常、自定义异常, 传递异常
2016/06/20 Python
遗传算法之Python实现代码
2017/10/10 Python
详解Django之admin组件的使用和源码剖析
2018/05/04 Python
Python求均值,方差,标准差的实例
2019/06/29 Python
Django中提供的6种缓存方式详解
2019/08/05 Python
python实现证件照换底功能
2019/08/20 Python
python3 图片 4通道转成3通道 1通道转成3通道 图片压缩实例
2019/12/03 Python
基于Python+QT的gui程序开发实现
2020/07/03 Python
pycharm中选中一个单词替换所有重复单词的实现方法
2020/11/17 Python
For Art’s Sake官网:手工制作的奢华眼镜
2018/12/15 全球购物
zooplus意大利:在线宠物商店
2019/08/07 全球购物
如何开启linux的ssh服务
2013/06/03 面试题
募捐倡议书怎么写
2014/05/14 职场文书
理财学专业自荐书
2014/06/28 职场文书
就业协议书样本
2014/08/20 职场文书
大学生职业生涯规划大赛作品(精品)
2014/09/17 职场文书
小学生毕业评语
2014/12/26 职场文书
建筑工程催款函
2015/06/24 职场文书
Python爬虫之自动爬取某车之家各车销售数据
2021/06/02 Python
mysql如何配置白名单访问
2021/06/30 MySQL
JAVA SpringMVC实现自定义拦截器
2022/03/16 Python