今天在写归并排序时,代码感觉没什么毛病,但却跑不出结果来,不得其解,感觉流程并没什么毛病。
void merge(int *a, int left, int mid, int right)
{
int len = sizeof(a) / sizeof(a[0]);
int temp[len];
int l = left;
int m = mid + 1;
int i = left;
while (l <= mid && m <= right)
{
if (a[l] < a[m])
{
temp[i++] = a[l++];
}
else
{
temp[i++] = a[m++];
}
}
while (l <= mid)
{
temp[i++] = a[l++];
}
while (m <= right)
{
temp[i++] = a[m++];
}
while (left <= right)
{
a[left] = temp[left];
left++;
}
}
void merge_sort(int *a, int left, int right)
{
if (left < right)
{
int mid = (right + left) / 2;
merge_sort(a, left, mid);
merge_sort(a, mid + 1, right);
merge(a, left, mid, right);
}
}
代码和课本上基本没有区别,但是一运行就是不输出结果,直接停了。室友说可能出现了死循环,归并经常有这种情况。
后来,我调试了下代码,发现问题出在merge里的len。当数组作为函数参数传递时,它会被解析为指针。因此,在merge函数内部,a
被视为一个指向整数的指针,而不是一个数组。所以,sizeof(a)
实际上返回的是指针的大小(4字节或8字节),而不是数组的大小。
所以len要作为一个参数提前传入归并函数中,而不是在函数内用sizeof计算,或者不用数组,直接用vector形式,就省掉了这个麻烦。
修正代码如下:
void merge(int *a, int left, int mid, int right, int len)
{
int temp[len];
int l = left;
int m = mid + 1;
int i = left;
while (l <= mid && m <= right)
{
if (a[l] < a[m])
{
temp[i++] = a[l++];
}
else
{
temp[i++] = a[m++];
}
}
while (l <= mid)
{
temp[i++] = a[l++];
}
while (m <= right)
{
temp[i++] = a[m++];
}
while (left <= right)
{
a[left] = temp[left];
left++;
}
}
void merge_sort(int *a, int left, int right, int len)
{
if (left < right)
{
int mid = (right + left) / 2;
merge_sort(a, left, mid, len);
merge_sort(a, mid + 1, right, len);
merge(a, left, mid, right, len);
}
}
看似简单,但是也足够细节。