.
数组排序的本质就是在比较数据的大小,看起来简单的大小比较随着数组长度的增加会变的非常繁杂。简单来看,更少的比较次数显然会有更好的性能,反应到编程语言里就是更少的循环次数。下面是我对几种常见排序算法的理解
1.冒泡排序:
/*从小到大的冒泡排序*/ function bubbleSort(array){ var end = array.length-1; while(end>0){/*这一层为循环次数,次数为数组长度-1*/ for(var i=0;i<end;i++){/*这一层进行比较,从左到右相邻的捉对比较,每循环1次,捉对比较次数少一次*/ if(array[i]>array[i+1]){ var md = array[i+1]; array[i+1] = array[i]; array[i] = md; } } end--; } } /** *要点: *1.有两层循环比较 *2.外层循环的次数是(数组长度-1次);内层循环次数初始也是(数组长度-1),且每循环1次后自减1。 *3.内层循环的方式是,根据数组元素下标从小到大,相邻两个元素依次捉对比较1次,并进行数值交换,把更大的数值交换给下标更大的元素。 *4.每次内层循环结束都会得到一个最大值,这个最大值也最终会被交换给本次内层循环中下标最大的数组元素。 *5.每次内层循环挑出的最大值都不用再参与下一次内层循环,所以每次内层循环结束后,内层循环次数减1次(因为上次内层循环结束得到的最大值元素不再需要参与比较,即参与比较的数组元素个数会减1)。 *6.上面代码中用一个变量end做为内层和外层共用的循环结束条件比较巧妙,充分利用了算法的两个特点: a.内层循环次数、外层循环初始次数相等 b.内层循环次数(变量end)逐次减1,外层循环条件中的变量(变量end)也是逐次减1 **/
2插入排序
/*从小到大插入排序*/ function insertSort(arr){ var count=arr.length; var end=1;/*取无序区最左边的1个元素*/ while(end<count){ var pos=end; for(var i=end-1;i>=0;i--){/*拿无序区最左边的元素分别与有序区从右到左的每个元素比较*/ var temp=arr[i]; if(arr[pos]<arr[i]){ arr[i]=arr[pos]; arr[pos]=temp; pos=i; }else{ break;/*适当的中止循环*/ } } end++; } return arr; } /** *1.插入排序算法原理(): 也是两层循环 根据数组下标先后顺序,从左到右列出所有数组元素,任意取两个相邻元素a,b; 假设a和a左边的数据为有序区,b和b右边的数据为无序区; 内层循环:拿无序区的数据e,依照有序区从右到左的次序,逐个与有序区的数据比较,遇到比e更大的数就交换数值,直到在有序区遇到比e更小或者相等的数,结束本轮内层循环 外层循环:每一个无序区的数据都要执行一次内层循环 初始取第二个数组元素为a 外层循环的次数是(数组长度-1); 内层循环的结束条件是:在有序区遇到更小或者相等的数,或者达到本轮最大循环次数 每次内层循环结束后,有序区的数据个数会增加1个; 每轮内层循环最大循环次数比前一轮内层循环最大循环次数多1次(实际循环次数则不一定), **/
3.快速排序
function quickSort(arr){ var count=arr.length; if(count<=1) return arr; var pos=Math.floor(count/2);/*算出中间位置*/ var val=arr.splice(pos,1)[0];/*取出中间位置的元素值作为基准值,并从原数组中移除*/ var left=[];/*存放比基准值小的数*/ var right=[];/*存放比基准值大的数*/ for(var i=0;i<arr.length;i++){/*对移除了中间元素的数组从左到右依次取元素与基准值比较*/ if(arr[i]<=val){ left.push(arr[i]); }else{ right.push(arr[i]); } } return quickSort(left).concat([val],quickSort(right));/*把左数组、基准值、右数组合并返回*/ } 或者 function quickSort(arr){/*取数组第一个元素为基准值作比较*/ var count=arr.length; if(count<=1) return arr; var left=[]; var right=[]; for(var i=1;i<count;i++){ if(arr[0]<arr[i]){ right.push(arr[i]); }else{ left.push(arr[i]); } } return quickSort(left).concat(arr[0],quickSort(right)); } /** *这种算法逻辑比较复杂,但是最快的一种,据说比内置的排序方法sort还要快 *1在数据集之中,选择一个元素作为"基准"(pivot)。 *2所有小于"基准"的元素,都移到"基准"的左边;所有大于"基准"的元素,都移到"基准"的右边。 *3对"基准"左边和右边的两个子集,不断重复第一步和第二步,直到所有子集只剩下一个元素为止。 **/
4.选择排序
function selectSort(array){ var i=0; var count=array.length; while(i<count){ var min=null; /*找出无序区的最小值元素*/ for(var j=i;j<count;j++){ if( min>array[j] || min===null){ min=array[j]; index=j; } } /*把无序区中的最小值和无序区的首元素值交换*/ if(index !== i){ var md=array[i]; array[i]=min; array[index]=md; } i++ } return array; } /** *也是将数组元素划分为无序和有序区,找出无序区中的最小值和无序区的首元素交换,无序区减少1个,循环至最终完成全部排序。 **/
经过chrome浏览器测试发现冒泡排序,插入排序,快速排序,系统的sort排序的性能表现:
数组长度在1000时:5ms以内, 5ms以内, 5ms以内 1ms左右
数组长度在2000时: 10ms以内, 10ms~20ms, 10ms~20ms; 10ms以内
数组长度在5000时: 50ms~60ms, 20ms~30ms, 10ms~20ms; 10ms左右
数组长度在10000时:250ms+, 80ms+, 30ms~50ms; 20ms以内
数组长度在50000时:1900ms+, 6000ms+, 少于150ms; 50ms左右
数组长度100000时: 300ms~400ms 100ms以内
数组长度500000时: 4100ms~4300ms 200ms以内
由此可见,系统的sort排序完胜,冒泡排序性能最弱
下面是冒泡排序,插入排序,快速排序,系统的sort排序的性能测试代码:
var start; var now; var arr=[]; for(var i=0;i<1000;i++){/*自动生成指定长度的数组*/ arr.push(random(1,1000)); } start=+new Date();/*开始排序时间点*/ charu(arr); //maopao(arr); //quickSort(arr); //arr.sort(function(a,b){return a-b;}); now=+new Date();/*排序结束时间点*/ console.log(now-start); function random(min,max){ return Math.ceil(Math.random()*(max-min))+min; } function maopao(arr){ var count=arr.length-1; var temp=0; while(count>0){ for(var i=0;i<count;i++){ if(arr[i]>arr[i+1]){ temp=arr[i]; arr[i]=arr[i+1]; arr[i+1]=temp; } } count--; } return arr; } function quickSort(arr){ var count=arr.length; if(count<=1) return arr; var left=[]; var right=[]; for(var i=1;i<count;i++){ if(arr[0]>arr[i]){ left.push(arr[i]); }else{ right.push(arr[i]); } } return quickSort(left).concat(arr[0],quickSort(right)); } function charu(arr){ var count=arr.length; var pos=1; var temp; while(pos<count){ var j=pos; for(var i=pos-1;i>=0;i--){ if(arr[i]>arr[j]){ temp=arr[i]; arr[i]=arr[j]; arr[j]=temp; j=i; }else{ break; } } pos++; } return arr; }