归并排序原理:
一开始先把数组从中间划分成两个子数组,一直递归的把子数组划分成更小的子数组,直到子数组里面只有一个元素才开始排序。
排序的方法就是按照大小顺序合并两个元素,接着依次按照递归的返回顺序,不断地合并排好序的子数组,直到最后把整个数组的顺序排好。
归并 排序合并:
合并函数实现的其实就是如何把两个有序的数组合并成一个数组
代码一:
比较常见的有序数组合并代码,也比较好理解
public void merge(int[] nums,int low,int mid,int high){
int copy[]=nums.clone();
int i=low,k=low,j=mid+1;
while(i<=mid&&j<=high){
if(copy[i]<copy[j]){
nums[k++]=copy[i++];
}else{
nums[k++]=copy[j++];
}
}
while(i<=mid) nums[k++]=copy[i++];
while(j<=high) nums[k++]=copy[j++];
}
代码二:比较简洁,理解难度较难
public void mergeSortInstance(int[] nums,int low,int high){
if(low>=high) return;
int mid=low+(high-low)/2;
mergeSortInstance(nums,low,mid);
mergeSortInstance(nums,mid+1,high);
merge(nums,low,mid,high);
}
/**
* 注释代码为错误代码,功能呢实现逻辑是不对的,而且也会抛出ArrayIndexOutOFBund
* 虽然错误代码与正确代码看起来就是 if条件执行的先后顺序不一样,但是这不一样就会导致整个代码的错误。在错误代码中,每次都是先判断i指针与指针指向的两个数的大小
* 例如对 1、5、9、7,8,6四个数归并,当i=0,mid=0,j=1时 执行 nums[k++]=copy[i++] 此时nums中的 值为1;i=1,k=1 执行nums[k++]=copy[j++]此时nums中的 值为1,5; k=2,j=2 退出
* 当i=2,mid=2,j=3时,执行nums[k++]=copy[j++]; 此时nums中的 值为1,5,7; 此时k=2,j=4 执行nums[k++]=copy[j++] 此时nums中的 值为1,5,7,8;
*
* @param nums
* @param low
* @param mid
* @param high
*/
public void merge(int[] nums,int low,int mid,int high){
int copy[]=nums.clone();
int i=low,k=low,j=mid+1;
/*while(k<=high){
if(copy[i]<copy[j]){
nums[k++]=copy[i++];
}else if(copy[j]<copy[i]){
nums[k++]=copy[j++];
}else if(i>mid){
nums[k++]=copy[j++];
}else{
nums[k++]=copy[i++];
}
}*/
while(k<=high){
if(i>mid)
nums[k++]=copy[j++];
else if(j>high)
nums[k++]=copy[i++];
else if(copy[j]<copy[i])
nums[k++]=copy[j++];
else
nums[k++]=copy[i++];
}
}
算法分析:稳定排序算法
空间复杂度:合并N个元素需要分配一个大小为n的额外数组,合并完成之后该数组被释放,空间复杂度为o(n)。
时间复杂度:T(n)=2*T(n/2)+O(n) 整体的复杂度为O(nlogn)