归并排序
思想:把数列中的数字进行分组,直到不能再分,即每组只有一个数字,再把相邻的两组做排序合并,直到所有的组都被合并。
举例:9,7,3,4,2
分组:
第一轮结果{9,7},{3,4,2}
第二轮结果{9},{7},{3},{4,2}
第三轮结果{9},{7},{3},{4},{2}
排序合并:
第一轮结果 {9},{7},{3},{2,4}
第二轮结果 {7,9},{2,3,4}
第三轮结果 {2,3,4,7,9}
应该说思想不难理解。记录下来的主要原因是感慨递归实现时的算法巧妙。
先贴代码吧。
package cn.tx.algorithm.quicksort;
public class Mergesort {
public static void main(String[] args) {
int A[] = {10,32,7,99,80,60,40,41,40,40,48};
int nSize = A.length;
int B[] = new int[nSize];
copy(A,B);
splitAndMerge(B,0,nSize,A);
for (int i = 0; i < nSize; i++) {
System.out.print(A[i] + ",");
}
}
//拷贝数组
static void copy(int[] src,int[] obj)
{
int nSize = src.length;
for (int i = 0; i < nSize; i++) {
obj[i] = src[i];
}
}
//递归分组、排序
static void splitAndMerge(int[] src,int nStart,int nEnd ,int[] obj)
{
if(nStart >= nEnd - 1)
return;
int nMiddle = (nStart + nEnd) / 2;
//接下来的两个函数的调用,对调了输入是src,obj顺序,这真是太聪明了。
splitAndMerge(obj,nStart,nMiddle,src);
splitAndMerge(obj,nMiddle,nEnd,src);
//因为上述两个递归调用对调了src和obj,所以每次回到外层时src就是里层的obj,保证了数据源总是最新的。
merge(src,nStart,nMiddle,nEnd,obj);
}
//排序
static void merge(int[] src,int nStart,int nMiddle,int nEnd ,int[] obj)
{
int i = nStart;
int j = nMiddle;
for(int nIndex = nStart ; nIndex < nEnd; nIndex ++) {
if(i < nMiddle && (j >= nEnd || src[i] < src[j])) {
obj[nIndex] = src[i];
i ++;
}
else {
obj[nIndex] = src[j];
j ++;
}
}
}
}
前边说写得巧妙的是这个函数:
//递归分组、排序
static void splitAndMerge(int[] src,int nStart,int nEnd ,int[] obj)
{
if(nStart >= nEnd - 1)
return;
int nMiddle = (nStart + nEnd) / 2;
//接下来的两个函数的调用,对调了输入是src,obj顺序,这真是太聪明了。
splitAndMerge(obj,nStart,nMiddle,src);
splitAndMerge(obj,nMiddle,nEnd,src);
//因为上述两个递归调用对调了src和obj,所以每次回到外层时src就是里层的obj,保证了数据源总是最新的。
merge(src,nStart,nMiddle,nEnd,obj);
}
我已经写了注释,其他就不赘述了。