合并两个有序数组
归并算法的中心是归并两个已经有序的数组。
归并两个有序数组A和B,就生成了第三个有序数组C,数组C包含数组A和B的所有数据项。
package recursion;
import java.lang.reflect.Array;
import java.util.Arrays;
public class RecursionTest5 {
public static void main(String[] args) {
int[] c = merge(new int[] {1,3,5,7},new int[] {2,4,6,8,10});
System.out.println(Arrays.toString(c));
}
//循环实现归并
public static int[] merge(int[] a, int[] b){
int[] c = new int[a.length+b.length];//初始化合并后的数组
//定义三个指针,分别作用于数组a,b,c
int aNum=0;
int bNum=0;
int cNum=0;
//实现归并
while (aNum<a.length && bNum<b.length){
//当a和b中都有剩余的元素的时候
if(a[aNum]<b[bNum]){
c[cNum ++] = a[aNum ++];
}else {
c[cNum ++] = b[bNum ++];
}
}
//如果b数组先取完,a有剩余
while (bNum == b.length && aNum<a.length){
c[cNum ++] = a[aNum ++];
}
//如果a数组先取完,b有剩余
while (aNum == a.length && bNum<b.length){
c[cNum ++] = b[bNum ++];
}
return c;
}
}
实现归并排序
归并排序的思想是把一个数组分成两半,排序每一半,再将两个有序数组合并为一个数组(如上节所示)。
那么如何为每一部分排序呢?使用递归:
将每一半都分为四分之一,对每个四分之一进行排序,然后把它们归并为一个有序的二分之一。
类似的,将每个四分之一分成两个八分之一…
依此类推,反复的分割数组,直到得到的子数组是一个数据项,一个数据项元素的数组肯定是有序的,那这就是这个递归算法的边界值。
也就是一直二分,分到只有一个元素,然后开始归并。
package recursion;
import java.util.Arrays;
public class RecursionTest6 {
public static void main(String[] args) {
int[] rs = mergeSort(new int[] {3,2,1,0,-1},0,4);
System.out.println(Arrays.toString(rs));
}
//实现归并排序
public static int[] mergeSort(int[] c, int l, int h){
// 要排序的无序数组,排序开始的下边界,排序结束的上边界
if(l>=h){//递归边界
//什么都不做
}else {
int mid = (l+h)/2;
//对两个子数组分别排序
mergeSort(c,l,mid);
mergeSort(c,mid+1,h);
//把上面排好序的有序数组进行归并
merge(c,l,mid,h);
}
return c;
}
//实现两个数组合并方法
public static void merge(int[] c, int l, int mid, int h){
//数组,下边界,中间值,上边界
int i = l; //左边数组的第一个
int j = mid+1; //右边数组的第一个
int[] tmp = new int[h-l+1]; //临时数组
int k = 0;//临时数组的索引
//实现合并
while (i<=mid && j<=h){
if(c[i]<c[j]){
tmp[k++] = c[i++];
}else {
tmp[k++] = c[j++];
}
}
while (i<=mid && j>h){
tmp[k++] = c[i++];
}
while (i>mid && j<=h){
tmp[k++] = c[i++];
}
//临时数组转移到C数组中
for(int g=0;g<tmp.length;g++){
c[l+g] = tmp[g];
}
}
}