以升序为例
void MergeSort(int *nums, int numsSize)
{
int* temp = (int*)malloc(sizeof(int) * numsSize);
…………;
free(temp);
}
void _MergeSort(int *nums, int *temp, int left, int right)
{
…………;
}
void MergeSort(int *nums, int numsSize)
{
int* temp = (int*)malloc(sizeof(int) * numsSize);
_MergeSort(nums, temp, 0, numsSize - 1);
free(temp);
}
void _MergeSort(int *nums, int *temp, int left, int right)
{
if (left >= right)
return;
…………;
}
void _MergeSort(int *nums, int *temp, int left, int right)
{
if (left >= right)
return;
int mid = (right - left) / 2 + left;
_MergeSort(nums, temp, left, mid);
_MergeSort(nums, temp, mid + 1, right);
……………;
}
[left,mid]和[mid + 1,right]
是有序的,存在两种情况:
{9,2}
,进入函数_MergeSort()
后,其子序列是单个数字,满足left >= right
的条件,直接退出递归,开始合并。{9,2,5,4}
,进入函数_MergeSort()
后,子序列{9,2}
递归,合并后退出递归,然后子序列{5,4}
递归,合并,退出递归,最后就变成了两个有序序列{2,9}和{4,5}
的合并void _MergeSort(int *nums, int *temp, int left, int right)
{
if (left >= right)
return;
//递归分割
int mid = (right - left) / 2 + left;
_MergeSort(nums, temp, left, mid);
_MergeSort(nums, temp, mid + 1, right);
int begin1 = left, end1 = mid;
int begin2 = mid + 1, end2 = right;
int index = left;
//归并
while (begin1 <= end1 && begin2 <= end2)
{
if (nums[begin1] > nums[begin2])
temp[index++] = nums[begin2++];
else
temp[index++] = nums[begin1++];
}
while (begin1 <= end1)
temp[index++] = nums[begin1++];
while (begin2 <= end2)
temp[index++] = nums[begin2++];
//将temp暂时存储的数据覆盖待排序列nums原有位置的数据,实现待排序列区间有序
for (int i = left; i <= right; i++)
nums[i] = temp[i];
}
void _MergeSort(int *nums, int *temp, int left, int right)
{
if (left >= right)
return;
//递归分割
int mid = (right - left) / 2 + left;
_MergeSort(nums, temp, left, mid);
_MergeSort(nums, temp, mid + 1, right);
int begin1 = left, end1 = mid;
int begin2 = mid + 1, end2 = right;
int index = left;
//归并
while (begin1 <= end1 && begin2 <= end2)
{
if (nums[begin1] > nums[begin2])
temp[index++] = nums[begin2++];
else
temp[index++] = nums[begin1++];
}
while (begin1 <= end1)
temp[index++] = nums[begin1++];
while (begin2 <= end2)
temp[index++] = nums[begin2++];
//将temp暂时存储的数据覆盖待排序列nums原有位置的数据(拷贝回去),实现待排序列区间有序
for (int i = left; i <= right; i++)
nums[i] = temp[i];
}
void MergeSort(int *nums, int numsSize)
{
int* temp = (int*)malloc(sizeof(int) * numsSize);
_MergeSort(nums, temp, 0, numsSize - 1);
free(temp);
}
gap < numsSize
,然后就进行和递归相同的合并操作就可以了void MergeSort(int* nums, int numsSize)
{
int* temp = (int*)malloc(sizeof(int) * numsSize);
int gap = 1;
while (gap < numsSize)
{
/*
因为每次是对两个有序序列进行合并
因此每次合并过后i应该跳过两个序列长度
*/
for (int i = 0; i < numsSize; i += 2 * gap)
{
int begin1 = i, end1 = i + gap - 1;
int begin2 = i + gap, end2 = i + 2 * gap - 1;
int index = begin1;
//归并
while (begin1 <= end1 && begin2 <= end2)
{
if (nums[begin1] < nums[begin2])
temp[index++] = nums[begin1++];
else
temp[index++] = nums[begin2++];
}
while(begin1 <= end1)
temp[index++] = nums[begin1++];
while(begin2 <= end2)
temp[index++] = nums[begin2++];
//将temp暂时存储的数据覆盖待排序列nums原有位置的数据(拷贝回去),实现待排序列区间有序
for (int j = i; j <= end2; j++)
nums[j] = temp[j];
}
gap *= 2;
}
free(temp);
}
{5,4,3,2,9,7,1,6,8}
{5,4,3,2,9,7
int begin1 = i, end1 = i + gap - 1;
int begin2 = i + gap, end2 = i + 2 * gap - 1;
int index = begin1;
/*
如果右半区间不存在,只有左半区间
说明待合并的只有一个区间
显然没有合并的必要,直接退出合并循环即可
*/
if (begin2 >= numsSize)
break;
//如果右半区间算多了,那么对end2进行修正
if (end2 >= numsSize)
end2 = numsSize - 1;
void MergeSort(int* nums, int numsSize)
{
int* temp = (int*)malloc(sizeof(int) * numsSize);
int gap = 1;
while (gap < numsSize)
{
/*
因为每次是对两个有序序列进行合并
因此每次合并过后i应该跳过两个序列长度
*/
for (int i = 0; i < numsSize; i += 2 * gap)
{
int begin1 = i, end1 = i + gap - 1;
int begin2 = i + gap, end2 = i + 2 * gap - 1;
int index = begin1;
/*
如果右半区间不存在,只有左半区间
说明待合并的只有一个区间
显然没有合并的必要,直接退出合并循环即可
*/
if (begin2 >= numsSize)
break;
//如果右半区间算多了,那么对end2进行修正
if (end2 >= numsSize)
end2 = numsSize - 1;
//归并
while (begin1 <= end1 && begin2 <= end2)
{
if (nums[begin1] < nums[begin2])
temp[index++] = nums[begin1++];
else
temp[index++] = nums[begin2++];
}
while(begin1 <= end1)
temp[index++] = nums[begin1++];
while(begin2 <= end2)
temp[index++] = nums[begin2++];
//将temp暂时存储的数据覆盖待排序列nums原有位置的数据(拷贝回去),实现待排序列区间有序
for (int j = i; j <= end2; j++)
nums[j] = temp[j];
}
gap *= 2;
}
free(temp);
}