排序是必然的要求。前端也不例外。虽然不多,但你一定会遇到的。但是说到排序,最容易想到的就是冒泡排序、选择排序和插入排序。冒泡排序依次比较相邻的两个元素,如果后一个比前一个小,就交换它们,这样从头到尾一次,把最好的放在最后。从头到尾再做一遍,由于每一轮都完成了,最新的已经是最好的了,所以下一轮需要比对的次数可以比上一轮少一次。虽然你还是可以让他从头到尾比较,但是后面的比较是没有意义也没有用的。为了效率,您应该优化代码。图片演示如下:代码实现:functionbubbleSort(arr){varlen=arr.length;for(vari=0;iarr[j+1]){//相邻元素两两比较vartemp=arr[j+1];//元素交换arr[j+1]=arr[j];arr[j]=温度;}}}returnarr;}SelectsortSelectsort我觉得最简单的,大一学VB的时候只记得这个排序方法,原理很简单:在每行找一个***或者最小的行每次开始。先在未排序的序列中找到最小(最大)的元素,将其存入已排序序列的开头,然后继续从剩余未排序的元素中寻找最小(最大)的元素,然后放在已排序序列的末尾.重复第二步,直到所有元素都排序完毕。动画演示:代码演示:functionselectionSort(arr){varlen=arr.length;varminIndex,temp;for(vari=0;i=0&&arr[preIndex]>current){arr[preIndex+1]=arr[preIndex];preIndex--;}arr[preIndex+1]=当前;}returnarr;}simple代价是效率低下。以上三种都是很简单的排序方法。同时,效率也会比较低。拿本书中的对比图来说明:时间复杂度高达O(n^2),而后面的一些排序算法的时间复杂度基本只有O(nlogn)。我的强迫症又犯了,想要一个更高效的排序方式。归并排序简单的翻了一遍这本书的内容,当时就理解了这个归并排序,所以这里就说说这个归并排序。基本原理是分治法,就是分开递归排序。步骤如下:申请一个大小为两个排序序列之和的空间,这个空间用来存放合并后的序列;设置两个指针,初始位置分别为两个排序序列的起始位置;比较两个指针所指向的元素,选择一个比较小的元素放入合并空间,将指针移动到下一个位置;重复步骤3,直到指针到达序列的末尾;直接将另一个序列的所有剩余元素复制到序列的合并端。动画演示:代码示例:functionmergeSort(arr){//采用自上而下的递归方法varlen=arr.length;如果(len<2){返回arr;}varmiddle=Math.floor(len/2),left=arr.切片(0,中间),右=arr。切片(中间);返回合并(合并排序(左),合并排序(右));}functionmerge(left,right){varresult=[];while(left.length&&right.length){if(left[0]<=right[0]){结果。推(左移());}其他{结果。推(右移());}}while(left.length)result.push(left.shift());while(right.length)result.push(right.shift());returnresult;}既然我是一个折腾的人,折腾你就得看效果了。效率测试因为我了解到这个排序不是简单的数组,数组里面全是对象,要对对象的一个??属性进行排序,还要考虑升序和降序。所以我的代码实现如下:/***[mergesort]*@param{[Array]}arr[待排序数组]*@param{[String]}prop[排序字段,当数组成员为一个对象,根据其中一个属性排序,简单数组直接排序忽略此参数]*@param{[String]}order[排序方式省略或asc为升序或降序]*@return{[Array]}[排序后的数组,一个新数组,不是对原数组的修改]*/varmergeSort=(function(){//合并var_merge=function(left,right,prop){varresult=[];//对数组中的其中一个成员进行属性排序if(prop){while(left.length&&right.length){if(left[0][prop]<=right[0][prop]){result.push(left.shift());}else{result.push(right.shift());}}}else{//数组成员直接排序while(left.length&&right.length){if(left[0]<=right[0]){结果.push(left.shift());}else{result.push(right.shift());}}}while(left.length)result.push(left.shift());while(right.length)result.push(right.shift());返回结果;};var_mergeSort=function(arr,prop){//使用自上而下的递归方法varlen=arr.length;如果(len<2){返回arr;}varmiddle=Math.floor(len/2),left=arr.slice(0,middle),right=arr.slice(middle);返回_merge(_mergeSort(left,prop),_mergeSort(right,prop),prop);};返回函数(arr,prop,顺序){varresult=_mergeSort(arr,prop);if(!order||order.toLowerCase()==='asc'){//升序返回结果;}else{//降序var_=[];结果.forEach(函数(项目){_.unshift(项目);});返回_;}};})();不确定需要对哪个属性进行排序,可以随意指定,所以写成参数。因为不想每次循环都判断这些东西,代码有点冗余。关于降序的问题,并没有加到参数中,只是简单的先升序输出再倒序。原因是不想每次循环递归都去判断条件,这样好处理。下面是见证效率的时间,一段数据模拟:vargetData=function(){returnMock.mock({"list|1000":[{name:'@cname',age:'@integer(0,500)'}]}).list;};上面使用Mock模拟数据,关于Mock:http://mockjs.com/实际测试来了://效率测试vararr=getData();console.time('合并排序');mergeSort(arr,'age');console.timeEnd('合并排序');console.time('冒泡排序');for(vari=0,l=arr.length;iarr[j+1].age){temp=arr[j+1];arr[j+1]=arr[j];arr[j]=温度;}}}console.timeEnd('冒泡排序');五次,效果如下://归并排序:6.592ms//冒泡排序:25.959ms//归并排序:1.334ms//冒泡排序:20.078ms//归并排序:1.085ms//冒泡排序:16.420ms//归并排序:1.200ms//冒泡排序:16.574ms//归并排序:2.593ms//冒泡排序:12.653ms***4次,将近16倍的效率差异还是比较满意的。虽然1000条数据被前端排序的可能性不大,但是几十条、几百条数据的情况还是有的。另外,因为node和javascript也可以跑server,这个效率提升还是有用的。有点怀疑Mergesort用的是递归。在《数据结构与算法 JavaScript 描述》中,作者给出了一种自下而上的迭代方法。但是对于递归的方法,笔者认为:但是在JavaScript中是做不到的,因为递归太深,语言无法处理。但是,这种方法在JavaScript中是行不通的,因为这种算法的递归深度对它来说太深了。gitbook上的书作者有疑惑,我也有疑惑。虽然merging用的是recursion,但是放在return之后。关于返回后的递归,有尾递归优化。关于尾递归优化,是指如果在外层函数内部调用了另一个函数,由于外层函数需要等待内层函数返回后才能返回结果,进入内层函数后,外层函数的信息必须存储在内存中。live,也就是调用栈。而inner函数是放在return关键字后面的,也就是说outer函数到这里就结束了。进入内层函数后,无需记住外层函数中的所有信息。以上是我的理解描述,不知是否准确。尾递归优化的功能在chrome下已经可以开启了。我认为这个递归应该不会影响它在JavaScript下的使用。***如果你有兴趣,我推荐你阅读这本书。排序的时候,可以考虑一些效率更高的方法。但是需要注意的是,这些高效的排序方式一般都需要比较大的额外内存空间,需要权衡。此外,非常小规模的数据是不必要的。一是影响太小,但是我们人的效率。我们可以在一分钟内从头写出一个冒泡、选择、插入的排序方法,但是归并排序呢?