归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治(divide-and-conquer)策略(分治法将问题分(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之)。
private var arrTest:Array=[9, 8, 7, 6, 5, 4, 3, 11, 21, 12, 2, 1, 0, 63];
/** 辅助数组,避免频繁new数组开辟内存空间以及传递不必要的数组,这里直接在外面new一次,归并排序时直接调用 */
private var temp:Array=[];
/**
* 将两个有序数组arr[left...mid]和arr[mid...right]合并
* @param arr
* @param left
* @param mid
* @param right
* 总的时间复杂度为O(n)
*/
private function mergerArr(arr:Array, left:int, mid:int, right:int):void
{
var i:int=left;
var j:int=mid + 1;
var m:int=mid;
var n:int=right;
var k:int=0;
//此处while时间复杂度为O(n)
while (i <= m && j <= n)
{
if (arr[i] <= arr[j])
{
temp[k]=arr[i];
i++;
//temp[k++] = arr[i++];
}
else
{
temp[k]=arr[j];
j++;
//temp[k++] = arr[j++];
}
k++;
}
//某一个子数组扫描完了,另一个子数组还有元素没有被扫描过,则直接往新数组末尾插入
while (i <= mid)
{
temp[k]=arr[i];
k++;
i++;
}
while (j <= n)
{
temp[k]=arr[j];
k++;
j++;
}
//时间复杂度为O(n)
var a:Array=[];
for (var l:int=0; l < k; l++)
{
arr[left + l]=temp[l];
a.push(temp[l]);
}
console.log("--------" + a.join(',') + "--------");
}
/**
* 将无序数组arr递归拆分成有序子数组(数组长度为1时视为有序)
* @param arr
* @param left
* @param right
*
*/
private function mergerSort(arr:Array, left:int, right:int):void
{
if (left < right)
{
var mid:int=Math.floor((left + right) / 2);
//使左边有序
mergerSort(arr, left, mid);
console.log();
//使右边有序
mergerSort(arr, mid + 1, right);
//将左右两边的有序子数组合并
mergerArr(arr, left, mid, right);
var arrLeft:Array=[];
var arrRight:Array=[];
for (var i:int=left; i <= right; i++)
{
if (i <= mid)
{
arrLeft.push(arr[i]);
}
else
{
arrRight.push(arr[i]);
}
}
console.log("合并了子数组[" + arrLeft.join(',') + "]和[" + arrRight.join(',') + "]");
}
}
通过添加打印信息可以看到归并排序的内部排序过程
先将无序数组拆分成长度为1的数组,此时视为有序,然后对左边子数组递归调用归并排序,再对右边子数组递归调用归并排序,最后对左右两个子数组调用归并排序。
归并排序每次将子数组一分为二,直至子数组长度为1或者0,需要拆分的次数为,每次合并子数组的时间复杂度为O(n),所以归并排序总的时间复杂度为O(nlgn),且最好最坏平均时间复杂度都为O(nlgn)。
考虑到归并排序每次都是在相邻的数据中进行操作,所以归并排序在O(nlgn)的几种排序方法中(快速排序,归并排序,希尔排序,堆排序)相对而言,效率较高。
分治思想常用于海量数据处理,例如,计算机内存只有1G,但是现在需要对2G的数据进行排序,无法一次性将所有数据加载到内存,这时候就可以采用分治策略,将数据根据某种方法拆分为小的数组集合(小于计算机内存),对各部分数据集合单独加载到计算机内存排序,各部分排完序之后,再将各部分数据集合合并成大的数据集合。