归并排序是利用递归的思想的。我们可以类比递归函数 sort(n) = M(sort(n1) , sort(n2))(并已经sort(1) = 常数); 对应的递归函数,我们知道要求sort(n)的值,必须先求得sort(n1),sort(n2)的值,然后带入M()函数,求得最后sort(n)的值。 拿归并函数和这个做类比, 就是要求得大数组的排序结果, 必须先求得其已经排序好的两个子数组的排序结果, 然后在利用合并函数,把两个已经排序好的子数组合并成为一个排序好的大数组(若子数组元素只有一个,那么已经排好序了, 这就是我们往下递归的终止条件,一旦满足这个条件,递归就开始回升)。
//编写一个Merge函数
public static void merge(int[] a, int p, int q, int r){
//分步走 1.得到两个有序的子数组 2.对两个组数组进行遍历比较,得到合并数组
//技巧1.在最后一个位置放置哨兵元素,使得遍历比较过程永远不会得到半途停止
//1. 得到两个子数组
if(!(p<=q && q<r)){
System.out.println("errro input p, q, r.");
return;
}
int l1 = q-p+1;
int l2 = r- q;
int[] leftArray = new int[l1+1];
int[] rightArray = new int[l2+1];
for(int i =0; i<l1; i++){
leftArray[i] = a[p+i];
}
leftArray[l1] = Integer.MAX_VALUE;
for(int i=0;i<l2;i++){
rightArray[i] = a[q+1+i];
}
rightArray[l2] = Integer.MAX_VALUE;
//2.遍历比较法合并两个子数组
int i = 0;
int j = 0;
for(int k=p; k<=r; k++){
if(leftArray[i] < rightArray[j])
a[k] = leftArray[i++];
else {
a[k] = rightArray[j++];
}
}
}
//递归的思想构造归并排序 可以类比递归函数 排序类比求值
public static void mergeSort(int[] a, int p, int r){
if(p<r){
int q = (p+r)/2;
mergeSort(a, p, q);
mergeSort(a, q+1, r);
merge(a, p, q, r);
}
}
以下是测试代码和测试结果
public static void main(String[] args) {
// TODO Auto-generated method stub
//测试归并排序
int[] a = new int[10];
for(int i =0; i<a.length; i++){
a[i] = (int)(Math.random()*20);
}
showArray(a);
mergeSort(a, 0, 9);
showArray(a);
}
结果:
4 0 14 8 14 17 17 2 10 5
0 2 4 5 8 10 14 14 17 17
总结:递归排序的算法充分的体现了递归的思想,这种递归的思想是基于分治法的思想,就是把大的问题,分成规模小的子问题的思想。