归并排序源码
//合并
void Merge(int arr[],int start,int end,int mid,int* tmp) {
int i_start = start;
int i_end = mid;
int j_start = mid + 1;
int j_end = end;
int length = 0;
while (i_start <= i_end && j_start <= j_end )
{
if (arr[i_start] < arr[j_start])
{
tmp[length] = arr[i_start];
i_start++;
length++;
}
else
{
tmp[length] = arr[j_start];
j_start++;
length++;
}
}
while (i_start <= i_end)
{
tmp[length] = arr[i_start];
i_start++;
length++;
}
while (j_start <= j_end)
{
tmp[length] = arr[j_start];
j_start++;
length++;
}
//辅助空间数据覆盖原空间
for (int i = 0; i < length; i++)
arr[start + i] = tmp[i];
}
//归并排序
void MSort(int arr[], int start, int end, int* tmp) {
if (start >= end)
return;
int mid = (start + end) / 2;
//分组
MergeSort(arr, start, mid, tmp);
MergeSort(arr, mid + 1, end, tmp);
Merge(arr, start, end, mid, tmp);
}
void MergeSort(int arr[], int length) {
int* tmp = (int*)malloc(sizeof(int) * length);
MSort(arr[], 0, length - 1, tmp);
}
上述的归并排序引入了大量递归,尽管在代码上比较清晰,容易理解,但这会造成时间和空间上的性能损耗。我们排序追求的就是效率,如果能将递归转化为迭代,那么性能上就能再提升一步,幸运的是这是可行的。采用非递归的迭代方法,避免了递归时深度为log2N的栈空间,空间只是用到了申请归并临时用的tmp数组,所以空间复杂度为O(N),所以使用归并排序时,可以尽量使用非递归的方法。
//合并,注意这里的Merge我是做了点修改的,和前面的有点不一样
void Merge(int arr[],int start,int end,int mid,int* tmp) {
int i_start = start;
int i_end = mid;
int j_start = mid + 1;
int j_end = end;
int length = start;
while (i_start <= i_end && j_start <= j_end )
{
if (arr[i_start] < arr[j_start])
tmp[length++] = arr[i_start++];
else
tmp[length++] = arr[j_start++];
}
while (i_start <= i_end)
tmp[length++] = arr[i_start++];
while (j_start <= j_end)
tmp[length++] = arr[j_start++];
//辅助空间数据覆盖原空间
for (int i = start; i < length; i++)
arr[i] = tmp[i];
}
void Mergepass(int arr[], int tmp[], int s, int n)
{
int i = 0;
//俩俩合并
while (i <= n - 2 * s)
{
Merge(arr, i, i + 2 * s - 1, i + s - 1, tmp);
i = i + 2 * s;
}
if (i < n - s)
Merge(arr, i, n - 1, i + s - 1, tmp);
else
for (int j = i; j < n; j++)
arr[j] = tmp[j];
}
//非递归实现归并排序,合并函数还是使用上述的Merge()函数
void MergeSort2(int arr[], int length) {
int* tmp = (int*)malloc(sizeof(int) * length);
int k = 1;
while(k < length)
{
Mergepass(arr, tmp, k, length);
k = 2*k;
}
}
好吧,我在这三个都用tmp这个参数名,导致我在修改bug的时候看的很乱,反正就是搞了我很久,里面的一些细节我就不再剖析了。下次如若在复习到这里再说吧,头疼。