Reputation: 1203
Trying to implement a naive merge sort using pointer arithmetic, but it's returning non-sense results. I'm following the convention that l
is the leftmost valid index and r
is the rightmost valid index.
The input is 5 1 3 2 4
but it returns: 0 1 0 2 5
and naturally the expected output is 1 2 3 4 5
.
#include <stdio.h>
void mergeptr(int *array, int l, int m, int r)
{
int tmp[r - l + 1];
int *tptr = &(tmp[0]);
int *lptr = &(array[l]);
int *rptr = &(array[m]);
/* Find the smallest in each side */
while ((lptr < &array[m]) && (rptr < &array[r]))
if (*lptr <= *rptr) *tptr++ = *lptr++;
else *tptr++ = *rptr++;
/* Copy the remaining */
while (lptr < &array[m]) *tptr++ = *lptr++;
while (rptr < &array[r]) *tptr++ = *rptr++;
/* Copy back */
for (size_t i = 0; i < (r-l+1); ++i)
array[l+i] = tmp[i];
}
void merge_sort(int *array, int l, int r) {
if (l < r) {
int m = (l + r) / 2;
merge_sort(array, l, m);
merge_sort(array, m + 1, r);
mergeptr(array, l, m, r);
}
}
int main(void) {
int values[5] = { 5, 1, 3, 2, 4 };
merge_sort(&values[0], 0, 4);
for (size_t i = 0; i < 5; ++i)
printf("%d ", values[i]);
printf("\n");
return 0;
}
I have tried to decouple those coupled pointers as *tptr = *lptr; tptr++; lptr++;
. To check if something as happening in wrong order but didn't change the outputs. Can't see where the the algorithm is failing.
Upvotes: 2
Views: 71
Reputation: 75062
You should be careful when you are dealing with boundaries.
It seems your merge_sort
function is dealing with the range [l, r)
(including l
, excluding r
), so:
m
shouldn't be execluded: merge_sort(array, m+1, r);
should be merge_sort(array, m, r);
if (l < r) {
should be if (l + 1 < r) {
r - l + 1
and r-l+1
in the function mergeptr
should be r - l
and r-l
.fixed code:
#include <stdio.h>
void mergeptr(int *array, int l, int m, int r)
{
int tmp[r - l];
int *tptr = tmp;
int *lptr = array + l;
int *rptr = array + m;
/* Find the smallest in each side */
while( (lptr < (array + m)) && (rptr < (array + r)))
if( *lptr <= *rptr) *tptr++ = *lptr++;
else *tptr++ = *rptr++;
/* Copy the remaining */
while(lptr < (array + m)) *tptr++ = *lptr++;
while(rptr < (array + r)) *tptr++ = *rptr++;
/* Copy back */
for(size_t i = 0; i < (r-l); ++i)
array[l+i] = tmp[i];
}
void merge_sort(int *array, int l, int r) {
if (l + 1 < r) {
int m = (l+r)/2;
merge_sort(array, l, m);
merge_sort(array, m, r);
mergeptr(array, l, m, r);
}
}
int main(void) {
int values[5] = { 5, 1, 3, 2, 4 };
merge_sort(values, 0, 5);
for(size_t i = 0; i < 5; ++i)
printf("%d ", values[i]);
printf("\n");
return 0;
}
Upvotes: 4