package textbookcode;
import java.util.*;
public class MERGESORT {
public static void main(String [] args){
Scanner in=new Scanner(System.in);
System.out.println("请输入数组的大小");
int N=in.nextInt();//从键盘读取数组的大小。
int A[]=new int [N];
System.out.println("请输入数组中的数");
for(int i=0;i<N;i++){//一次从键盘中读取输入的数。
A[i]=in.nextInt();
}
mergeSort(A,0,N-1);//调用归并函数。
System.out.println("按从小到大的顺序归并排序后为:");
for(int m=0;m<N;m++){
System.out.print(A[m]+" ");
}
}
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 merge(int A[],int p,int q,int r){//将两个有序的数组进行归并的代码。
int L[]=new int[q-p+1];
int R[]=new int[r-q];
int k,j;
for( k=0;k<=q-p;k++){
L[k]=A[p+k];
}
for(j=0;j<r-q;j++){
R[j]=A[q+1+j];
}/*将A数组从A[p]到A[r]经A[q]划分成两部分并存储在两个新数组中.
由于在mergeSort函数中经递归到最底层时只剩下由两个长度为1的数组数,所以这两个数组必然有序,
所以往回调用时A[p~q]和A[q+1~r]也必然是两个有序的数组。*/
k=0;
j=0;
for(int i=p;i<=r;i++){/*将两个数组比较大小往A[]中添加时还要分成两个部分添加。因为k和j总是在不定期的加1,而且A[]比两个数组都要大
所以要识别两个小数组是否越界*/
if(k<=q-p&&j<=r-q-1){//第一个部分:非越界部分怎样添加。
if(L[k]<R[j]){
A[i]=L[k];
k++;
}
else {
A[i]=R[j];
j++;
}
}
else{//第二部分:其中某个数组越界后,另一个数组中未添加的数一定比A[]中已经添加的数要大且有序,所以直接往后添加。
if(k>q-p){//L[]先越界,直接往A[]后添加R[]没有添加的部分。
A[i]=R[j];
j++;
}
else{//R[]先越界,直接往A[]后添加L[]没有添加的部分。
A[i]=L[k];
k++;
}
}
}
}
}
以数组A{5,2,4,7,1,3,2,6}中的8个数为例:
mergeSort(A,0,7)----A{5,2,4,7,1,3,2,6}
mergeSort(A,0,3)----A{5,2,4,7,1,3,2,6}
mergeSort(A,0,1)----A{5,2,4,7,1,3,2,6}
mergeSort(A,0,0)----A{5,2,4,7,1,3,2,6}
mergeSort(A,1,1)----A{5,2,4,7,1,3,2,6}
merge(A,0,1)数组A中0~0和1~1都有序,所以归并,但操作的还是数组A,只是元素范围是0~1.归并结果A{2,5,4,7,1,3,2,6}
mergeSort(A,2,3)----A{5,2,4,7,1,3,2,6}
mergeSort(A,2,2)---A{5,2,4,7,1,3,2,6}
mergeSort(A,3,3)---A{5,2,4,7,1,3,2,6}
merge(A,2,3)数组A中2~2和3~3都有序,所以归并,但操作的还是数组A,只是元素范围是2~3.归并结果A{2,5,4,7,1,3,2,6}
merge(A,0,3)数组A中0~1和2~3都有序,所以归并,归并结果A{2,4,5,7,1,3,2,6}
mergeSort (A,4,7)----A{2,5,4,7,1,3,2,6}同理,结果为A{2,5,4,7,1,2,3,6}
merge(A,0,7)数组A中0~3和4~7都有序,所归并,归并结果为A{1,2,2,3,4,5,6,7}