大家好,我是苏貝,本篇博客带大家了解归并排序,如果你觉得我写的还不错的话,可以给我一个赞👍吗,感谢❤️
目录
归并排序(用递归)
之前我们写了一篇博客来介绍如何用递归实现归并排序,那么不用递归也可以实现归并排序吗?是的
初步非递归归并排序:
注意:上面的图只是为了方便看才感觉是在原数组上修改的,实际上是先比较2个数组,之后将这2个数组合成的数组存入额外的数组tmp中,之后再拷贝回原数组。
2个要合并成一个有序数组的下标怎么表示呢?我们来以gap==2举例:
begin1=i , end1=i+gap-1 ,begin2=i+gap ,end2=i+2*gap-1
代码如下:
但是这段代码有些问题,你能看出来吗?
void MergeSortNonR(int* a, int n)
{
int* tmp = (int*)malloc(sizeof(int) * n);
if (tmp == NULL)
{
perror("malloc fail");
return;
}
int gap = 1;
while (gap < n)
{
for (int i = 0; i < n; i = i + 2 * gap)
{
int begin1 = i, end1 = i + gap - 1;
int begin2 = i + gap, end2 = i + 2 * gap - 1;
int j = begin1;
while (begin1 <= end1 && begin2 <= end2)
{
if (a[begin1] < a[begin2])
tmp[j++] = a[begin1++];
else
tmp[j++] = a[begin2++];
}
while (begin1 <= end1)
tmp[j++] = a[begin1++];
while (begin2 <= end2)
tmp[j++] = a[begin2++];
memcpy(a + i, tmp + i, sizeof(int) * (end2 - i + 1));
}
gap *= 2;
}
free(tmp);
}
问题:当原数组的数组元素不为2^n时,2个数组可能会越界,如下图:1还要与不是数组元素的值相比
所以我们要处理2个数组下标越界的可能
1. begin1越界
因为begin1被置为i,i<n,所以begin1不会越界
2. end1越界
就是上图的情况,此时第一个数组肯定有序,第二个数组肯定不存在,所以直接退出循环
3. begin2越界
begin2越界时,第二个数组肯定不存在,所以也不需要操作,直接退出循环
4. end2越界
当begin2没越界而end2越界时,只需将end2置为最后一个元素的下标n-1即可
代码:
void MergeSortNonR(int* a, int n)
{
int* tmp = (int*)malloc(sizeof(int) * n);
if (tmp == NULL)
{
perror("malloc fail");
return;
}
int gap = 1;
while (gap < n)
{
for (int i = 0; i < n; i = i + 2 * gap)
{
int begin1 = i, end1 = i + gap - 1;
int begin2 = i + gap, end2 = i + 2 * gap - 1;
if (end1 >= n || begin2 >= n)
break;
if (end2 >= n)
end2 = n - 1;
int j = begin1;
while (begin1 <= end1 && begin2 <= end2)
{
if (a[begin1] < a[begin2])
tmp[j++] = a[begin1++];
else
tmp[j++] = a[begin2++];
}
while (begin1 <= end1)
tmp[j++] = a[begin1++];
while (begin2 <= end2)
tmp[j++] = a[begin2++];
memcpy(a + i, tmp + i, sizeof(int) * (end2 - i + 1));
}
gap *= 2;
}
free(tmp);
}
好了,那么本篇博客就到此结束了,如果你觉得本篇博客对你有些帮助,可以给个大大的赞👍吗,感谢看到这里,我们下篇博客见❤️