经典排序算法[3]-归并排序
将归并排序之前,先解决一个问题,如何合并两个有序数组?
arr1 = [1,3,4,6]
arr2 = [2,3,7,9,10]
基本思路如下:
- 维护两个索引index1和index2分别代表arr1和arr2的某个位置的元素,初始值都是0,构造一个长度为两个数组长度之和的结果数组res[],res待写位置i初始为0,算法伪代码流程:
如果 arr1[index1]<=arr2[index2]
则 拷贝arr1[index1]的元素到结构数组的res[i] index1++ i++
否则 拷贝arr2[index2]的元素到结构数组的res[i] index2++ i++
直到 arr1或者arr2有一个越界就退出循环
如果arr1和arr2还有剩余元素为扫描,将其为扫描元素直接拷贝到结果数组
归并排序的主体思路就是上面那个,整体思路是:
- 1)、将待排序数组一分为2,假设为左子数组,又子数组
- 2)、使用归并排序算法对左子数组排序并返回左子数组排序结果
- 3)、使用归并排序算法对右子数组排序并返回右子数组排序结果
- 4)、对左右两个子数组的排序结果进行合并
代码实现如下:
public class MergeSort {
//递归
public static void process(int[] data,int L,int R){
if(L==R){
return;
}
int mid = L + ((R-L)>>1);
process(data,L,mid);
process(data,mid+1,R);
merge(data,L,mid,R);
}
private static void merge(int[] data, int L, int M, int R) {
// System.out.println("1");
int[] help = new int[R-L+1];
int i =0;
int p1=L;
int p2=M+1;
while(p1<=M && p2<=R){
help[i++] = data[p1]<=data[p2]?data[p1++]:data[p2++];
}
while(p1<=M){
help[i++]=data[p1++];
}
while(p2<=R){
help[i++]=data[p2++];
}
for (int j = 0; j < help.length ; j++) {
data[L+j]=help[j];
}
}
//非递归的写法
public static void mergeSort2(int[] data) {
if(data == null || data.length<2){
return;
}
int N = data.length;
int mergeSize = 1;
while(mergeSize < N){
int L = 0;
while(L< N){
int M = L+mergeSize-1;
if(M>=N){
break;
}
int R = Math.min(N-1,M+mergeSize);
merge(data,L,M,R);
L = R+1;
}
if(mergeSize>N/2){
break;
}
mergeSize<<=1;
}
}
public static void main(String[] args) {
int[] data = {5, 4, 3, 2, 1, 2, 3, 4, 5, 6};
// process(data,0,data.length-1);
mergeSort2(data);
System.out.println(Arrays.toString(data));
}
}