归并排序的思想:将一大段无序的数组,不断地拆分拆分最后拆成独立的个体,两两相互比较,接着进行归并,体现出递归分治的思想,这里将采用二路归并的方法解决问题。
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
void merge(int*nums,int lo,int mi,int hi,int*ans){
int i,j,k;
for(k=lo;k<=hi;++k)ans[k]=nums[k];
for(i=lo,j=mi+1,k=lo;j<=hi&&i<=mi;++k){
if(ans[i]<ans[j])nums[k] = ans[i++];
else nums[k] = ans[j++];
}
while(j<=hi)nums[k++]=ans[j++];
while(i<=mi)nums[k++]=ans[i++];
return;
}
void mergesort(int*nums,int lo,int hi,int*ans){
if(lo<hi){
//直到区间到最小的时候结束
int mi = (lo+hi) >> 1;
mergesort(nums,lo,mi,ans);
//前段
mergesort(nums,mi+1,hi,ans);
//后段
merge(nums,lo,mi,hi,ans);
//合并
}
return;
}
int* sortArray(int* nums, int numsSize, int* returnSize){
int *ans = (int*)malloc(sizeof(int)*numsSize);
*returnSize = numsSize;
mergesort(nums,0,numsSize-1,ans);
return nums;
}
解释: sortArray函数(主题函数)作用是构建一个ans数组和调用mergesort归并排序。
mergesort函数:常见的框架,建议记忆,先前段再后段最后进行归并,记住要在lo<hi条件成立的情况下。
merge函数:二路归并主体,引用邓俊辉老师课件,他在第二章描述的是B段进行另开空间取[lo,mi)和C段直接复制[mi,hi)。这里采用直接整段复制到另外一个数组ans的形式。在for循环执行二路归并,元素较小方放入nums里,不断重复最后直到i指针或k指针超出范围,则跳出for循环。
再有,因为由于某一个指针超出范围跳出了,还有剩余元素需要复制,这时候ans里面储存的函数都是有序的且均大于nums数组的最后一个数,所以直接用while循环设置两种条件,直接复制到nums数组上去就行了。
解析:这是mergesort的一个模块,对有序的两个数列进行归并(merge),思路比较简单。
//One of the model of the mergesort:merge
void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n){
int i,k,j;
int ans[200]={0};
if(m==0){
nums1[0]=nums2[0];
}
for(int cnt=0;cnt<m;cnt++)ans[cnt]=nums1[cnt];
for(i=0,j=0,k=i;i<m&&j<n;k++){
if(nums2[j]<ans[i])nums1[k]=nums2[j++];
else nums1[k]=ans[i++];
}
while(j<n){
nums1[k++]=nums2[j++];
}
while(i<m){
nums1[k++]=ans[i++];
}
}
解释:依然是分成A,B,C三段,A为main数组,B为前段数组,C为后段数组。for为归并排序主体,依然是二路归并的思路,谁小谁往下落,先处理后段,再处理前段。接着对溢出情况进行处理。