归并排序算法分析与实现
归并排序运用了分治法的思想。
两个有序子数组可以以O(n)的时间复杂度进行合并。
当有序子数组长度s=1时,数组中有n/1个有序子数组,合并后有序子数组长度加倍变为2。
当有序子数组长度s=2时,数组中有n/2个有序子数组,合并后有序子数组长度加倍变为4。
…
当有序子数组长度s=n/2时,数组中有2个有序子数组,合并后有序子数组长度加倍变为n。
此时数组已经完全有序。
时间复杂度分析:
s的序列是:1,2,4, 8,….log2(n)
因此划分子数组的操作的时间复杂度是log(n)
合并子数组的时间复杂度是O(n)
因此归并排序的时间复杂度是:O(n*log(n))
public class MergeSortDemo {
public static void main(String[] args) {
int arr[]={2,3,5,1,4,9,8,7,6,0};
MergeSort(arr);
for (int i : arr) {
System.out.println(i);
}
}
public static void MergeSort(int[] x){
int s=1;//字数组初始长度为1,只有单个元素的数组是有序的。
int n=x.length;
System.out.println("数组长度为:"+n);
int[] y=new int[n];//用于存储合并后的数组
while(s<n){
//将 n/s 个长度为 s 的子数组 合并到y数组中,有序的子数组的长度变为2s
MergePass(x,y,s,n);
s+=s;//长度加倍
//将 n/s 个长度为 s 的子数组 合并到y数组中,有序的子数组的长度变为2s
MergePass(y,x,s,n);
s+=s;//长度加倍
}
}
/*
* 合并总数组中的相邻子数组
* s:子数组长度
* n:总数组长度
*/
public static void MergePass(int []x,int[] y,int s,int n){
int i=0;
//剩余的未合并段的长度大于等于2*s时
while(n-i >= 2*s){
//合并大小为s的相邻两段子数组
Merge(x,y,i,i+s-1,i+s*2-1);
i+=2*s;
}
//剩下的未合并元素个数小于2s
if(n-i > s){//剩余的元素个数大于s
Merge(x,y,i,i+s-1,n-1);
}else {//剩余的元素个数小于等于s
for(int j=i;j<=n-1;j++){
y[j]=x[j];
}
}
}
/*
* 合并两个有序数组为一个有序数组
* l:第一个数组的左边界
* m:第一个数组的右边界(第二个数组的左边界就是m+1)
* r:第二个数组的左边界
* 第一个数组:x[l...m]
* 第二个数组:x[m+1...r]
*/
public static void Merge(int[] x,int []y,int l,int m,int r){
int i=l,j=m+1,k=l;
while((i<=m)&&(j<=r)){
if(x[i] <= x[j]){
y[k++]=x[i++];
}else {
y[k++]=x[j++];
}
}
if(i>m){
for(int q=j;q<=r;++q){
y[k++]=x[q];
}
}else {
for(int q=i;q<=m;++q){
y[k++]=x[q];
}
}
}
}