没有系统地总结过js算法,虽然在项目中陆陆续续的也用过好多算法,有一次去一家公司面试的时候,面试官说想谈谈算法,有点懵了,所以接下来的面试中谈的也有点被动,避免下次再碰到这种情况,今天决定好好的总结下js的各种算法。
1.插入排序
看到一篇直接插入排序讲的很好的文章,将插入排序与抽扑克牌进行对比,一直动态地添加扑克牌,添加时进行排序,等牌抽完了,手里的牌也整理好了。
转换成算法就是从第二个数据开始,依次与前面的数据进行比对,如果小于该数据,就将二者位置互换,这就是插入排序的原理。
function insertSort(array) { var len = array.length, i, j, tmp, result; result = array.slice(0); for(i=1; i < len; i++){ tmp = result[i]; j = i - 1; while(j>=0 && tmp < result[j]){ result[j+1] = result[j]; j--; } result[j+1] = tmp; } return result; }
2.二分插入排序
二分插入排序是在插入排序的基础上进行优化。
它的基本思想是将原序列分为有序区与无序区,从无序区取出一个元素,与有序区中间位置的元素进行比较,如果大于中间位置的元素,将该元素与有序区后半部分的元素进行比较,直至找到该元素的位置。同时将有序区原位置以后的所有元素后移。重复该操作,直至无序区全部添加至有序区。
function midSort(array) { var len = array.length, i, j, tmp, low, high, mid, result; result = array.slice(0); for(i = 1; i < len; i++){ tmp = result[i]; low = 0; high = i - 1; while(low <= high){ mid = parseInt((low + high)/2, 10); if(tmp < result[mid]) high = mid - 1; else low = mid + 1; } for(j = i - 1; j >= high+1; j--){ result[j+1] = result[j]; } result[j+1] = tmp; } return result; }
3.希尔排序
希尔(Shell)排序又称为缩小增量排序,它是一种插入排序。它是直接插入排序算法的一种威力加强版。
该方法因DL.Shell于1959年提出而得名。
希尔排序的基本思想是:
把记录按步长 gap 分组,对每组记录采用直接插入排序方法进行排序。
随着步长逐渐减小,所分成的组包含的记录越来越多,当步长的值减小到 1 时,整个数据合成为一组,构成一组有序记录,则完成排序。
我们来通过演示图,更深入的理解一下这个过程。
function shellSort(array){ var len = array.length, gap = parseInt(len/2), i, j, tmp, result; result = array.slice(0); while(gap > 0){ for(i = gap; i < len; i++){ tmp = result[i]; j = i - gap; while(j>=0 && tmp < result[j]){ result[j + gap] = result[j]; j = j - gap; } result[j + gap] = tmp; } gap = parseInt(gap/2); } return result; }
4.冒泡排序
冒泡排序是最经典的算法之一,他的原理是对数组进行若干次排序,每次排序对数组元素的相邻元素进行比较,每趟排序都需要找到第i个最小的元素。
function bubbleSort(arr){ var len = arr.length; var result = arr.slice(0); //外层控制轮数 for(var i=0;i<len;i++){ //标志某一趟排序过程中是否有数据交换 var mark = true; //内层对数组元素进行冒泡选择 for(var j=0;j<len-1-i;j++){ //判断当较小的元素位于下面时,冒泡 if(result[j] > result[j+1]){ mark = false; var temp = result[j]; result[j] = result[j+1]; result[j+1] = temp; } } if(mark){ //当某一趟排序时并没有进行数据交换,则说明所有数据已经有序 return result; } } }
5.选择排序
选择排序的原理是每次从待排序的无序列表中找到最小的数据,放在已排序的有序数组的最尾部。
简单排序流程:
(1)从待排序序列中,找到关键字最小的元素;
(2)如果最小元素不是待排序序列的第一个元素,将其和第一个元素互换;
(3)从余下的 N - 1 个元素中,找出关键字最小的元素,重复(1)、(2)步,直到排序结束。
function selectionSort(arr) { var len = arr.length-1,res=arr.splice(0),i; var minIndex, temp; for (i = 0; i < len; i++) { minIndex = i; for (var j = i + 1; j < len; j++) { if (res[j] < res[minIndex]) { //寻找最小的数 minIndex = j; //将最小数的索引保存 } } tmp = res[i]; res[i] = res[minIndex]; res[minIndex] =tmp; } return res; }
6.快速排序
快速排序是一种交换排序。
快速排序的基本思想是:
(1)将待排序的数组根据中间点分成两部分。
(2)将比该基准数据大的放在右边的数组,比基准数据小的放在左边的数组。
(3)对左右两个数组不断重复第一步和第二步,合并数组。
function quickSort(arr){ if(arr.length < 2){ return arr; } var tmp = arr.splice(Math.floor(arr.length/2), 1)[0], arrLeft = [], arrRight = []; for(var i = 0; i < arr.length; i++){ if(arr[i] >= tmp){ arrRight.push(arr[i]); }else{ arrLeft.push(arr[i]); } } return arguments.callee(arrLeft).concat(tmp,arguments.callee(arrRight)); }
前三种为插入排序,查的很多资料中讲各种排序算法时都提到了时间复杂度的概念,有时间学习下。
参考页面:
4.排序四 希尔排序
5.十大经典排序算法