参考:维基百科 以及 数据结构与算法分析——Java语言描述 (美)Mark Allen Weis 等
归并排序算法的时间复杂度是 O(n logn) ,最差空间复杂度O(n) ,是稳定的排序算法。
它是建立在归并操作上的一种有效的排序算法,是采用分治法(Divide and Conquer)的一个非常典型的应用。这个算法中的基本的操作是合并两个已排序的表。归并操作的过程如下:
- 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
- 设定两个指针,最初位置分别为两个已经排序序列的起始位置
- 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
- 重复步骤3直到某一指针达到序列尾
- 将另一序列剩下的所有元素直接复制到合并序列尾
下面的这幅图片说明了这个过程:
代码如下:
public class Sort {
public static void main(String[] args) {
Sort sort= new Sort();
int[] a={0,56,89,3,9,0,1,4,28,655,48,478,58,2658,98,145,33,66652,14,14};
sort.mergeSort(a);
for(int i=0;i<a.length;i++)
System.out.println(a[i]);
}
/**
* @param a:要排序的数组
*/
public void mergeSort(int[] a){
int[] tmpArr=new int[a.length];
mergeSort(a, tmpArr, 0, a.length-1);
}
/**
*
* @param a:要排序的数组
* @param tmpArr:
* @param left:开始下标
* @param right:结束下标
*/
public void mergeSort(int[] a,int[] tmpArr,int left,int right){
if(left<right){
int center=(left+right)/2;
mergeSort(a, tmpArr, left, center);
mergeSort(a, tmpArr, center+1, right);
merge(a, tmpArr, left, center, right);
}
}
/**
* 合并两个有序序列
* @param a:这两个有序序列其实是a的左右部分
* @param tmpArr:用来存放合并结果的临时数组
* @param lBegin:左边序列的开始下标
* @param lEnd:左边序列的结束下标
* @param rEnd:右边序列的结束下标
*/
public void merge(int[] a,int[] tmpArr,int lBegin,int lEnd,int rEnd){
int num=rEnd-lBegin+1;
int rBegin=lEnd+1;
int tmpPos=lBegin;
while(lBegin<=lEnd && rBegin<=rEnd)
if(a[lBegin]<=a[rBegin])
tmpArr[tmpPos++]=a[lBegin++];
else
tmpArr[tmpPos++]=a[rBegin++];
while (lBegin<=lEnd)
tmpArr[tmpPos++]=a[lBegin++];
while(rBegin<=rEnd)
tmpArr[tmpPos++]=a[rBegin++];
// tmpArr是排好序的数据,将它copy回a,注意方式,因为我们不知道开始下标,却知道结束下标
for(int i=0;i<num;i++)
{
a[rEnd]=tmpArr[rEnd];
rEnd--;
}
}
}