归并排序,其的基本思路就是将数组分成二组A,B,如果这二组组内的数据都是有序的,那么就可以很方便的将这二组数据进行排序。如何让这二组组内数据有序了?
可以将A,B组各自再分成二组。依次类推,当分出来的小组只有一个数据时,可以认为这个小组组内已经达到了有序,然后再合并相邻的二个小组就可以了。这样通过先递归的分解数列,再合并数列就完成了归并排序。
此话摘自: 白话归并排序我的js写法:
//合并2个数组
function mergeArr(a,b){
var c=[], aLen = a.length, bLen = b.length;
for(var i=0,j=0;i<aLen&&j<bLen;){
if(a[i]<b[j]){
c.push(a[i++]);
}else{
c.push(b[j++]);
}
}
var index,from;
i==aLen?(index=j,from=b):(index=i,from=a); //不能在三目运算符中使用var
concatArrTail(c,from,index);
function concatArrTail(to,from,index){
for(;index<from.length;){to.push(from[index++])}
}
return c;
}
function mergeSort(a){
var lastIndex = a.length-1;
if(a.length==1){return a;};
var mid = parseInt((0+lastIndex)/2);
var b= a.slice(0,mid+1); //截取0到mid之间的数组
var c =a.slice(mid+1,lastIndex+1);
var sortedB = mergeSort(b);
var sortedC = mergeSort(c);
return mergeArr(sortedB,sortedC);
}
测试:
var a=[5,1,3,6,2];
var sortedArr = mergeSort(a); //[1, 2, 3, 5, 6]
备注:
在这里2个函数的参数都是最简洁的方式:
1、合并数组传递2个数组类型的参数;
2、对数组归并排序只传递一个数组类型的参数;
这样可读性比较好
但是如果增加参数能减少空间的使用:
1、每次归并排序都要通过slice()方法将数组分成2部分,其实我们可以不用先切好,再作为参数,可以直接传入未切割的数组,和待切割的索引
将归并排序方法改成:
传入待排序的数组、数组中待排序的某一部分(前一部分或者后一部分)的开始索引、数组中待排序的某一部分(前一部分或者后一部分)的结束索引
把合并数组方法改成:
传入待排序的数组、数组中进行合并的前一部分的开始索引、数组中进行合并的分割索引(前一部分的结束索引也即后一部分的开始索引)、数组中进行合并的后一部分的结束索引;
2、每次合并数组都要创建一个数组,来保存合并后的数组,其实可以用一个变量作为参数,用来贯穿递归排序和和合并数组的全过程。