前端必会的七种排序算法
被前端面试中算法虐惨的小林准备大干一场,好好准备一下面试中的高频算法题,由于前端算法相比于后端手撕的算法较容易,所以小编准备从最基础的七种排序算法开始。前方高能,请抓住方向盘……
一、冒泡排序
冒泡排序的思路:遍历数组,然后将最大数沉到最底部;<br/>时间复杂度:O(N^2);<br/>空间复杂度:O(1)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | function BubbleSort(arr) { if (arr == null || arr.length <= 0){ return []; } var len = arr.length; for ( var end = len - 1; end > 0; end--){ for ( var i = 0; i < end; i++) { if (arr[i] > arr[i + 1]){ swap(arr, i, i + 1); } } } return arr; } function swap(arr, i, j){ // var temp = arr[i]; // arr[i] = arr[j]; // arr[j] = temp; //交换也可以用异或运算符 arr[i] = arr[i] ^ arr[j]; arr[j] = arr[i] ^ arr[j]; arr[i] = arr[i] ^ arr[j]; } |
二、选择排序
选择排序的实现思路:遍历数组,把最小数放在头部;<br/>时间复杂度:O(N^2);<br/>空间复杂度:O(1)
三、插入排序
插入排序实现思路:将一个新的数,和前面的比较,只要当前数小于前一个则和前一个交换位置,否则终止;<br/>时间复杂度:O(N^2);<br/>空间复杂度:O(1)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | function insertSort(arr) { if (arr == null || arr.length <= 0){ return []; } var len = arr.length; for ( var i = 1; i < len; i++) { for ( var j = i - 1; j >= 0 && arr[j] > arr[j + 1]; j--) { swap(arr, j, j + 1); } } return arr; } function swap(arr, i, j){ var temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } |
四、归并排序
归并排序的思路:<br/>1.先左侧部分排好序<br/>2.再右侧部分排好序<br/>3.再准备一个辅助数组,用外排的方式,小的开始填,直到有个动到末尾,将另一个数组剩余部分拷贝到末尾<br/>4.再将辅助数组拷贝回原数组<br/>*时间复杂度:O(N logN)<br/>空间复杂度:O(N)**
快速排序实现思路:随机取出一个值进行划分,大于该值放右边,小于该值放左边(该算法在经典快排的基础上经过荷兰国旗思想和随机思想进行了改造)<br/>*时间复杂度:O(NlogN) <br/>空间复杂度:O(logN)**
六、堆排序
堆排序思路:<br/>1.让数组变成大根堆<br/>2.把最后一个位置和堆顶做交换<br/>3.则最大值在最后,则剩下部分做 heapify,前端培训则重新调整为大根堆,则堆顶位置和该部分最后位置做交换<br/>4.重复进行,直到减完,则这样最后就调整完毕,整个数组排完序(为一个升序)<br/>*时间复杂度:O(N logN)<br/>空间复杂度:O(1)**
七、桶排序
桶排序会经历三次遍历:准备一个数组、遍历一遍数组、重构一遍数组,是非基于比较的排序,下面以一个问题来阐述其思路。<br/>问题:<br/> 给定一个数组,求如果排序之后,相邻两个数的最大差值,要求时间复杂度 O(N),且要求不能用基于比较的排序<br/>
思路:<br/>1.准备桶:数组中有 N 个数就准备 N+1 个桶<br/>2.遍历一遍数组,找到最大值 max 和最小值 min
。若 min = max,则差值=0;若 min≠max,则最小值放在 0 号桶,最大值放在 N 号桶,剩下的数属于哪个范围就进哪个桶<br/>3.根据鸽笼原理,则肯定有一个桶为空桶,设计该桶的目的是为了否定最大值在一个桶中,则最大差值的两个数一定来自于两个桶,但空桶两侧并不一定是最大值<br/>4.所以只记录所有进入该桶的最小值 min 和最大值 max 和一个布尔值表示该桶有没有值<br/>5.然后遍历这个数组,如果桶是空的,则跳到下一个数,如果桶非空,则找前一个非空桶,则最大差值=当前桶 min - 上一个非空桶 max,用全局变量更新最大值<br/>时间复杂度:O(N)<br/>空间复杂度:O(N)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | function maxGap(arr) { if (arr == null || arr.length <= 0) { return 0; } var len = arr.length; var max = -Infinity, min = Infinity; //遍历一遍数组,找到最大值max和最小值min for ( var i = 0; i < len; i++) { max = max > arr[i] ? max : arr[i]; min = min > arr[i] ? arr[i] : min; } //若min = max,则差值为0; if (min == max) { return 0; } var hasNum = new Array(len + 1); var mins = new Array(len + 1); var maxs = new Array(len + 1); var bid = 0; //指定桶的编号 for ( var i = 0; i < len; i++) { bid = bucket(arr[i], min, max, len); //获得该值是在哪个桶//由于有N+1个桶,所以间隔就是N个,所以此处除以的是len,然后通过这个函数得到应该放到哪个桶里 maxs[bid] = hasNum[bid] ? Math.max(arr[i], maxs[bid]) : arr[i]; mins[bid] = hasNum[bid] ? Math.min(arr[i], mins[bid]) : arr[i]; hasNum[bid] = true ; } var res = 0; var lastMax = maxs[0]; for ( var i = 0; i < len + 1; i++) { if (hasNum[i]) { res = Math.max(mins[i] - lastMax, res); lastMax = maxs[i]; } } return res; } //获得桶号 //这个函数用于判断在哪个桶中,参数分别为值、最小值、最大值、桶间隔 function bucket(value, min, max, len) { return parseInt((value - min) / ((max - min) / len)); } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通