归并排序的根本原理是将一个序列先分成一个一个小序列,分别完成排序,然后再将小序列两两合并,直到全部合并完成即排序结束。代码中也是使用这个思路,先将序列分成(n+1)/2个小序列,再慢慢合并,直到全部合并完成。
/* 合并序列,只用于合并相邻序列 */
void merge_arr(int *nums,int arr1_start,int arr2_start,int end)
{
int len = end+1-arr1_start;
int *p_arr = (int*)malloc(len*sizeof(int));
int arr1_idx = arr1_start;
int arr2_idx = arr2_start;
for(int i = 0;i < len;)
{
if(arr1_idx >= arr2_start)
{
p_arr[i++] = nums[arr2_idx++];
}
else if(arr2_idx > end)
{
p_arr[i++] = nums[arr1_idx++];
}
else
{
if(nums[arr1_idx] < nums[arr2_idx])
{
p_arr[i++] = nums[arr1_idx++];
}
else
{
p_arr[i++] = nums[arr2_idx++];
}
}
}
memcpy(nums+arr1_start,p_arr,len*sizeof(int));
free(p_arr);
}
/*
* 归并排序(merge sort)
* 1.将已有序的子序列合并,直到再无无序序列
* 实现原理:先将数列n分为n/2个序列,并使每个序列有序
* 再将有序序列两两合并,直到全部合并完成排序结束
* 这里都是将相邻序列合并,方便合并序列的执行
*/
void merge_sort(int *nums, int len)
{
int step = 1; // 初始合并的步长为2,后续依次乘2,直到长度大于数列长度结束
int idx = 0;
while(step < len)
{
// 将已划分的小序列排序
for(int i = 0;i < len;i+=step*2)
{
idx = i;
int arr2_start = idx+step;
int end = idx+step+step-1;
if(arr2_start > len)
{
break;
}
else if(end >= len)
{
merge_arr(nums,idx,arr2_start,len-1);
}
else
{
merge_arr(nums,idx,arr2_start,end);
}
}
step *= 2;
}
}