2D pointer arithmetic in C - c

I am attempting to swap 2 elements in a 2D array in C, with no luck.
Thanks for the answers so far, but I have edited this code to make things clearer about what I am doing.
typedef struct smystruct { /* stuff... */ } mystruct;
void nswap( mystruct ** a, mystruct ** b )
{
mystruct * tmp = *a;
*a = *b;
*b = tmp;
}
void nqsort( mystruct ** h, int m, int n )
{
double key = 0.0;
int i = 0, j = 0, k = 0;
if( m < n ) {
// choose the pivot point...
k = (m + n) / 2;
nswap( &h[ n ], &h[ k ] );
key = (*h+m)->prob;
i = m + 1;
j = n;
while ( i <= j ) {
while ( (i <= n) && (*h+i)->prob <= key )
i++;
while ( (j >= m) && (*h+j)->prob > key )
j--;
if ( i < j ) {
nswap( &h[i], &h[j] );
}
}
// swap two elements
nswap( &h[m], &h[j] );
// recursively sort the lesser list
nqsort( h, m, j-1 );
nqsort( h, j+1, n );
}
}
int main()
{
mystruct * p = NULL;
// get the number of nodes (m)...
fscanf( in, "%d", &m );
// allocate memory for the node and connectivity matrix arrays...
p = (mystruct*)malloc( sizeof( mystruct ) * m );
// read in the location and associated probabilities!...
for ( ; loop < m ; ++loop ) {
mystruct * tmpnode = p + loop;
tmpnode->str = (char*)malloc( sizeof( char ) * 1024 );
fscanf( in, "%s %lf", (char *)tmpnode->str, &tmpnode->prob );
}
nqsort( &p, 0, m );
}
Needless to say this does not work. I have searched for examples and nothing seems to work. Advise for the n00b would be appreciated.

The last element has index count-1, not count.
h[0] h[1] h[2] h[3] h[4] h[5] h[6] h[7] h[8] h[9]
----------------------------------------------------------
total 10 elements
I don't know what is fwnodes, perhaps you mean h.

Multiple stuff is wrong there.
1/ Your 2D array is badly allocated (or code is missing).
2/ A proper way to do such 2D allocation is to use Iliffe pointer (as advised in Numrical Recipes in C/C++).
mystruct** alloc_array( int h, int w )
{
int i;
mystruct** m = malloc(h*sizeof(mystruct*));
m[0] = malloc(h*w*sizeof(mystruct));
for(i=1;i<h;i++) m[i] = m[i-1]+w;
return m;
}
void release_array(mystruct** m)
{
free( m[0] );
free( m);
}
This way of allocating brings you both a contiguous block of memory (which is easier to handle, is more cache friendly, dont require to do some index computation) and a [][] access.
Your swap function then become :
void swap( mystruct* a, mystruct* b )
{
mystruct tmp = *a
*a = *b;
*b = tmp;
}
and can be called like :
swap( &some_tab[i][j], &some_other_tab[u][v] );
In a full example :
int main()
{
mystruct** my_array = alloc_array(3,4); /* 3x4 mystruct array */
/* fill the array */
/* Swap some */
swap( &my_array[2][1], &my_array[0][3] );
release_array(my_array);
}

You are passing pointer to array to your function. That means h has only one element.
swap( &p, 10 );
Should be:
swap( p, 10 );
That means you need to change your function to accept arrays of mystruct or change p to array of pointers to mystruct.
And, as KennyTM suggested the last element has index 9 not 10.

Related

Set typedef that can be 2 different types

I am trying to make a function that can receive a variable which can be a char or an int and for that I have to give the variable a type but I don't know what to put because I want it to be able to receive both.
My code is like this and i don't know what to put in the spot where is written 'IDK':
#include <stdio.h>
#include <string.h>
int is_string = 0;
#define less(A,B) (!is_string ? ((A)<(B)) : (strcmp(A,B)<0))
void merge(IDK a[], int l, int m, int r)
{
IDK aux[10000][20];
int i, j, k;
for (i = m+1; i > l; i--) aux[i-1] = a[i-1];
for (j = m; j < r; j++) aux[r+m-j] = a[j+1];
for (k = l; k <= r; k++){
if (less(aux[j], aux[i])) a[k] = aux[j--];
else a[k] = aux[i++];
}
}
void mergesort(IDK a[], int l, int r) {
int m = (r+l)/2;
if (r <= l)
return;
mergesort(a, l, m);
mergesort(a, m+1, r);
merge(a, l, m, r);
}
int main(){
mergesort(a,left,right);
}
I want the 'IDK' to be char when the variable is_stringis 1, and int when else...
The goal is to use the function to sort words alphabetically or numbers (lowest to highest), the function just has to sort one type of object at a time, but I want it to be able to sort both types of objects so I don't have to repeat code.
I want to have a program that chooses (at runtime) what type it needs to sort.
Thanks
The general approach of writing such functions in C is to declare a function that accepts a pointer of the type void * together with the number of elements in the passed array, the size of an object of the array element type and a comparison function similarly how the standard C function qsort is declared.
Here is a demonstrative program that shows such an approach.
The function merge can be written without allocating dynamically memory.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void merge( void *a, size_t m, size_t n, size_t size, int cmp( const void *, const void * ) )
{
void *p = malloc( n * size );
size_t i = 0, j = m;
char *pos = p;
while ( i < m && j < n )
{
if ( cmp( ( char * )a + j * size, ( char *)a + i * size ) < 0 )
{
memcpy( pos, ( char * )a + j * size, size );
++j;
}
else
{
memcpy( pos, ( char * )a + i * size, size );
++i;
}
pos += size;
}
if ( i < m )
{
memcpy( pos, ( char * )a + i * size, ( m - i ) * size );
}
if ( j < n )
{
memcpy( pos, ( char * )a + j * size, ( n - j ) * size );
}
memcpy( a, p, n * size );
free( p );
}
void mergesort( void *a, size_t n, size_t size, int cmp( const void *, const void * ) )
{
if ( n / 2 )
{
mergesort( a, n / 2, size, cmp );
mergesort( ( char * )a + n / 2 * size, n - n / 2, size, cmp );
merge( a, n / 2, n, size, cmp );
}
}
int cmp_int( const void *p1, const void *p2 )
{
int a = *( int * )p1;
int b = *( int * )p2;
return ( b < a ) - ( a < b );
}
int cmp_string( const void *p1, const void *p2 )
{
return strcmp( *( const char * const * )p1, *( const char * const * )p2 );
}
int main(void)
{
int a[] = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
const size_t N1 = sizeof( a ) / sizeof( *a );
for ( size_t i = 0; i < N1; i++ )
{
printf( "%d ", a[i] );
}
putchar( '\n' );
mergesort( a, N1, sizeof( *a ), cmp_int );
for ( size_t i = 0; i < N1; i++ )
{
printf( "%d ", a[i] );
}
putchar( '\n' );
char * s[] = { "J", "I", "H", "G", "F", "E", "D", "C", "B", "A" };
const size_t N2 = sizeof( s ) / sizeof( *s );
for ( size_t i = 0; i < N2; i++ )
{
printf( "%s ", s[i] );
}
putchar( '\n' );
mergesort( s, N2, sizeof( *s ), cmp_string );
for ( size_t i = 0; i < N2; i++ )
{
printf( "%s ", s[i] );
}
putchar( '\n' );
return 0;
}
The program output is
9 8 7 6 5 4 3 2 1 0
0 1 2 3 4 5 6 7 8 9
J I H G F E D C B A
A B C D E F G H I J
You're looking for a union, but that won't work with your calls to scanf and printf. They expect a certain type of argument depending on the format modifier, in this case expecting an int or int* for modifier "%d".
union IDK
{
int int_val;
char *string_val;
};
void merge(union IDK a[], int l, int m, int r);
What you read from the console is always a string. scanf can convert it to a number, if that's what you ask for with "%d". But it appears that what you really are looking for is a way to sort strings that may consist of digits. The easiest way to do that is to try to convert it using strtol.
There's another pitfall you should be aware of. strcmp compares the ASCII values of characters. This won't sort alphabetically, if that's what you're looking for.
Note that a generalized sorting function is usually implemented by passing it a void*, the number of elements, the size of those elements, and a function pointer to a comparison function. See qsort for an example.

swapping last element problem in sorting C array

I am trying to write a sorting algorithm using a function that finds the adress of the minimum element in the array:
#include <stdio.h>
int * findMin(int * start,int * end) ///function to return the adress of the smallest array element
{
int *min = start;
int x;
int size = (end - start);
for(x=0; x<size; x++)
{
if (*(start+x)<*min)
min = (start+x);
}
return min;
}
But here in my sort algorithm, since the last element has nothing more to compare itself with, is mistakenly left as it is
void sort(int * start, int * end) ///funtion to sort the array in ascending order
{
int x,temp;
int size = (end - start);
for (x = 0; x <size; x++)
{
if ( *(start+x) > *findMin(start,end))
{
temp = *findMin(start+x,end);
*findMin(start+x,end) = *(start+x);
*(start+x) = temp;
}
}
}
int main()
{
int arr[10]={5,11,3,12,17,25,1,9,14,2};
sort(arr,&arr[9]);
for(int i=0;i<10;i++)
printf("%d ",arr[i]);
printf("\n");
}
How can I correct this?
The expression in this declaration
int size = (end - start);
does not give the exact size of the array. At least you should write
int size = end - start + 1;
However it is not a good idea to pass the pointer to the last element of the array instead of the pointer to the memory after the last element of the array. In this case you can specify an empty range as start is equal to end.
Also if the function accepts two pointers then there is no need to introduce intermediate variables used as indices in loops.
And this code snippet
temp = *findMin(start+x,end);
*findMin(start+x,end) = *(start+x);
*(start+x) = temp;
is very inefficient.
Here is a demonstrative program that shows how the functions can be implemented.
#include <stdio.h>
int * findMin( const int * start, const int * end ) ///function to return the adress of the smallest array element
{
const int *min = start;
if ( start != end )
{
while ( ++start != end )
{
if ( *start < *min ) min = start;
}
}
return ( int * )min;
}
void selection_sort( int *start, int *end ) ///funtion to sort the array in ascending order
{
for ( ; start != end; ++start )
{
int *min = findMin( start, end );
if ( min != start )
{
int tmp = *start;
*start = *min;
*min = tmp;
}
}
}
int main(void)
{
int arr[] = { 5, 11, 3, 12, 17, 25, 1, 9, 14, 2 };
const size_t N = sizeof( arr ) / sizeof( *arr );
for ( const int *p = arr; p != arr + N; ++p )
{
printf( "%d ", *p );
}
putchar( '\n' );
selection_sort( arr, arr + N );
for ( const int *p = arr; p != arr + N; ++p )
{
printf( "%d ", *p );
}
putchar( '\n' );
return 0;
}
The program output is
5 11 3 12 17 25 1 9 14 2
1 2 3 5 9 11 12 14 17 25
But here in my sort algorithm, since the last element has nothing more to compare itself with, is mistakenly left as it is
No, that's at best a misleading characterization. Your findMin() does not specifically compare array elements to their immediate successors, so the fact that *end has no successor is irrelevant. The problem is (in part) simply that you have an off-by-one error, resulting in never comparing *end with *min. That mistake would be harder to make and easier to recognize if you relied more directly on pointer arithmetic and comparisons:
int *findMin(int *start, int *end) {
int *min = start;
// The original code is equivalent to this variant:
// for (int *x = start; x < end; x++) {
// but this is what you need for an inclusive upper bound:
// for (int *x = start; x <= end; x++) {
// or, since initially min == start, this would be even better:
for (int *x = start + 1; x <= end; x++) {
if (*x < *min) {
min = x;
}
}
return min;
}

Quick sort in C — pointers and memory

I am a computer science freshman and I still have some difficulties when it comes to pointers. I am trying to implement a quick sort program in C.I currently have 2 errors but I am not able to figure out how to fix it.
On the main function, when I am calling partition, I got an Incompatible pointer types
On the swap function: Thread 1: EXC_BAD_ACCESS (code=1, address=0x200000007)
void swap(int *i, int* j){
*i = *j;
*j = *i;
*i = *j;
}
void partition(int* array[], int size){
int pivot = size;
int i = - 1;
for(int j = 0 ; j < size - 1 ; j++){
if(array[j] < array[pivot]){
i++;
swap(array[i],array[j]);
}
}
}
int main() {
int array[] = {7,2,1,8,6,3,5,4};
int size = sizeof(array)/sizeof(array[0]);
partition(&array,size);
return 0;
}
For starters if an array has N elements then the valid range of indices is [0, N-1]
Thus there is an attempt to access memory beyond the array
int pivot = size;
int i = - 1;
for(int j = 0 ; j < size - 1 ; j++){
if(array[j] < array[pivot])
^^^^^^^
Your function swap does not make sense.
void swap(int *i, int* j){
*i = *j;
*j = *i;
*i = *j;
}
After the first expression statement
*i = *j;
the both objects pointed to by the pointers i and j will have the same value.
The function can be defined the following way.
void swap( int *p, int *q )
{
int tmp = *p;
*p = *q;
*q = tmp;
}
and called like
swap( &array[i], &array[j] );
The function partition is also invalid. Apart from the incorrect used algorithm at least its first parameter is declared also incorrectly.
Instead of
void partition( int* array[], int size );
the function should be declared like
void partition( int *array, int size );
or more correctly like
void partition( int *array, size_t size );
and the function should be called like
int array[] = {7,2,1,8,6,3,5,4};
size_t size = sizeof(array)/sizeof(array[0]);
partition( array,size );
On the other hand, the function partition should return the position that divides the array into two parts. So the final function declaration will look like
size_t partition( int array[], size_t size );
Below there is a demonstrative program that shows how a recursive function quick sort can be written using functions swap and partition.
#include <stdio.h>
void swap( int *p, int *q )
{
int tmp = *p;
*p = *q;
*q = tmp;
}
size_t partition( int a[], size_t n, int pivot )
{
size_t i = 0;
while ( i != n )
{
while ( i != n && a[i] < pivot ) i++;
while ( i != n && !( a[--n] < pivot ) );
if ( i != n ) swap( a + i, a + n );
}
return i;
}
void quick_sort( int a[], size_t n )
{
if ( n != 0 )
{
size_t pos = partition( a, n - 1, a[n - 1] );
swap( a + pos, a + n - 1 );
quick_sort( a, pos );
quick_sort( a + pos + 1, n - pos - 1 );
}
}
int main(void)
{
int a[] = { 7, 2, 1, 8, 6, 3, 5, 4 };
const size_t N = sizeof( a ) / sizeof( *a );
for ( size_t i = 0; i < N; i++ )
{
printf( "%d ", a[i] );
}
putchar( '\n' );
quick_sort( a, N );
for ( size_t i = 0; i < N; i++ )
{
printf( "%d ", a[i] );
}
putchar( '\n' );
return 0;
}
The program output is
7 2 1 8 6 3 5 4
1 2 3 4 5 6 7 8
There are a few problems in here:
The pointer notation has the weird effect that the star comes after the thing it points to, so the int* array[] in partition is an array of pointers to integers, while what you call it with in main is a pointer to an array of integers.
An array[] is actually a pointer by itself (though with some slightl technical differences, but in general something that accepts a pointer will also accept an array). You are mainly using the array in partition as an array of integers (the array[j] < array[pivot] should be a comparison of content, but with an int* array[] it is a comparison of address), so you should change it to just being an int array[]. Note that this will also help with resolving point 1, as you just need to remove the superflous referencing when you call partition.
When you index an array it counts as a dereferencing, so when you call swap(array[i],array[j]) (assuming you have made the corrections suggested above) you are passing ints and not int*s, you need to change it to swap(&array[i],&array[j]).
In swap you are setting both of their values to j's. This happens because the information of what is in i is destroyed when you write over it. There are several ways to handle this, the 2 main ones are saving the information in a temporary variable, and the second is through bit-hacking. Here are 2 examples:
void swap(int *i, int* j){
int temp = *j;
*j = *i;
*i = temp;
}
An a version using exlusive or:
void swap(int *i, int* j){
*i= *j ^ *i;
*j= *j ^ *i;
*i= *j ^ *i;
}
pointers
I wasn't sure if the question was asking about a pointer based quicksort, so here is an example, using Lomuto partition scheme. In the partition loop, it recurses on the smaller part, and loops back for the larger part, limiting stack space to O(log(n)), but worst case time complexity remains at O(n^2).
void QuickSort(int *lo, int *hi)
{
int *pi;
int *pj;
int pv;
int t;
while (lo < hi){
pv = *hi; /* pivot */
pi = lo; /* partition */
for (pj = lo; pj < hi; ++pj){
if (*pj < pv){
t = *pi; /* swap *pi, *pj */
*pi = *pj;
*pj = t;
++pi;
}
}
t = *pi; /* swap *pi, *hi */
*pi = *hi; /* to place pivot */
*hi = t;
if(pi - lo <= hi - pi){ /* recurse on smaller part */
QuickSort(lo, pi-1); /* loop on larger part */
lo = pi+1;
} else {
QuickSort(pi+1, hi);
hi = pi-1;
}
}
}

convert information of struct of an pointer to array

I have a problem with a for loop, which should put information of struct of a pointer to an array. This struct is for complex numbers. The problem is the numbers m[n].re/.im -they are not korrekt.
typedef struct
{
float re, im;
} Complex;
#define N 2
#define M 2
int main()
{
Complex* p;
Complex matrix[N][M]; //already filled
Complex m[N*M];
int n;
n = 0;
p = NULL;
for(p = &matrix[0][0]; p<= &matrix[0][0]+N*M-1; p++)
{
m[n] = *p;
n = n+1;
}
}
You can use standard C function memcpy declared in header <string.h> for example
memcpy( m, matrix, N * M * sizeof( Complex ) );
If you want to use a loop that uses pointers then it can look for example the following way
for ( Complex *q = ( Complex * )matrix, *p = m; q != ( Complex * )matrix + N * M; p++, q++ )
{
*p = *q;
}
I've modified your program to initialize the matrix array, and to print to stdout the values of matrix and the array m after the copy using the for loop:
#include <stdio.h>
typedef struct
{
float re, im;
} Complex;
#define N 2
#define M 2
int main()
{
Complex* p;
Complex matrix[N][M]; //already filled
Complex m[N*M];
int idx, jdx, val = 1;
for (idx = 0; idx < N; idx++) {
for (jdx = 0; jdx < M; jdx++) {
matrix[idx][jdx].re = val;
matrix[idx][jdx].im = val;
++val;
}
}
int n;
n = 0;
p = NULL;
for (p = &matrix[0][0]; p < &matrix[0][0] + N*M; p++)
{
printf("matrix[%d] = %f + %fi\n", n, p->re, p->im);
m[n] = *p;
n = n+1;
}
int midx = 0;
for (midx = 0; midx < N*M; midx++) {
printf("m[%d] = %f + %fi\n", midx, m[midx].re, m[midx].im);
}
return 0;
}
I'm not sure what happened but to me it just looks like you didn't initialize the arrays. Remember, memcpy is your friend. Hope this code helps.
I think the pointer p holds the address of a struct Complex. Not sure but try once like this
for(p = &matrix[0][0]; p<= &matrix[0][0]+N*M-1; p = p + sizeof(int))
{
m[n] = *p;
n = n+1;
}
}
The fastest way to do the copy is with memcpy, but if you want to use a loop, the code should look like this
Complex matrix[N][M];
Complex array[N*M];
Complex *p = array;
for ( int n = 0; n < N; n++ )
for ( int m = 0; m < M; m++ )
*p++ = matrix[n][m];
In response to the comment, given only a pointer to the matrix, and knowing the dimensions, it's possible to create a pointer that acts like a two dimensional array.
void someFunction( Complex *matrix, int sizeN, int sizeM )
{
Complex (*p)[sizeM] = (void *)matrix;
for ( int n = 0; n < sizeN; n++ )
for ( int m = 0; m < sizeM; m++ )
printf( "%f %f\n", p[n][m].re, p[n][m].im );
}

Reverse an integer array of length 2^n recursively and return a new array without modifying the original

I encountered the following question in an interview.
Complete this function to return a reversed array without modifying the function signature or the original array. Note that static data types should not be used here at all.
Assume the arrayLength is a power of 2. i.e 2^n. -> I think this is the trick here.
int* reverse(int *array, int arrayLength){
}
Please help.
Note that I could not really think of a solution to the problem. The interviewer hinted at using 2^n for the puspose, but i could not really think of the solution.
How about this:
int* reverse(int *array, int arrayLength){
if (arrayLength==1) {
int* out=(int*)malloc(sizeof(int));
out[0] = array[0];
return out;
}
int* left = reverse(array+arrayLength/2, arrayLength-arrayLength/2);
int* right = reverse(array,arrayLength/2);
int* out = (int*)realloc(left, sizeof(int)*arrayLength);
memcpy(out+arrayLength/2, right, sizeof(int)*(arrayLength/2));
free(right);
return out;
}
Agree with OP the the hint is "2^n". As with many recursive functions: divide and conquer.
This routine first deals with errant paramters and the simple lengths. Next, divide the length in half and reverse each half. Form the result by concatenating the reversed left and right sub-arrays. First, right, then left.
Usual clean-up follows
#include <string.h>
#include <stdlib.h>
int* reverse(int *array, int arrayLength) {
// Check parameters
if (array == NULL || arrayLength < 0) {
; // TBD HandleBadParameters();
}
// Allocate space for result, not much to do if length <= 1
int *y = malloc(arrayLength * sizeof *y);
if (y == NULL) {
; // TBD HandleOOM();
}
if (arrayLength <= 1) {
memcpy(y, array, arrayLength * sizeof *y);
return y;
}
// Find reverse of the two halves
int halflength = arrayLength / 2;
int *left = reverse(array, halflength);
int *right = reverse(&array[halflength], halflength);
// Append them to the result - in reverse order
memcpy(y, right, halflength * sizeof *y);
memcpy(&y[halflength], left, halflength * sizeof *y);
// Clean-up and return
free(right);
free(left);
return y;
}
int* reverse(int *array, int arrayLength){
if(arrayLength == 0) return array;
int* ret = (int*)malloc(arrayLength*sizeof(int));
for(int i=0;i<arrayLength;i++) ret[i] = array[arrayLength-1-i];
return reverse(ret, 0); // technically recursive
}
Here it is (and works):
int *reverse(int *array, int arrayLength)
{
if (arrayLength > 1) {
int i, n = arrayLength >> 1;
int *m = calloc(n, sizeof(int));
memcpy(m, array, n*sizeof(int));
memcpy(array, array + n, n*sizeof(int));
memcpy(array + n, m, n*sizeof(int));
free(m);
reverse(array, n);
reverse(array+n, n);
} /* for */
return array;
} /* reverse */
it can be done without temporary storage, but you have to iterate a little.
int *reverse(int *a, int al)
{
if (al > 1) {
int i, a1 = al >> 1;
for (i = 0; i < a1; i++) {
int temp = a[i];
a[i] = a[i + a1];
a[i + a1] = temp;
} /* for */
reverse(a, a1);
reverse(a+a1, a1);
} /* for */
return a;
} /* reverse */
but, it would be nicer just to exchange from the boundaries to the middle and do it completely iterative.
int *reverse(int *array, int arrayLength)
{
int a, b;
for (a = 0, b = arrayLength-1; a < b; a++, b--) {
int temp = array[a];
array[a] = array[b];
array[b] = temp;
} /* for */
return array;
} /* reverse */
And just for the ones who asked for a non selfmodifying array, this all-inefficient form:
int *reverse(int *array, int arrayLength)
{
int *a1, *a2;
int *res;
if (arrayLength > 1) {
int l = arrayLength >> 1;
a1 = reverse(array, l);
a2 = reverse(array + l, l);
res = calloc(arrayLength, sizeof(int));
memcpy(res, a2, l*sizeof(int));
memcpy(res+l, a1, l*sizeof(int));
free(a1);
free(a2);
} else {
/* we return always memory alloc'd with malloc() so we have to do this. */
res = malloc(sizeof(int));
*res = array[0];
} /* if */
return res;
} /* reverse */
Well, here's one sneaky way, and it doesn't care what length the array is. Note: I'm assuming you can't introduce a new function, it has to be done all within the existing function
if the length is postive, it allocates memory and makes a copy, then calls reverse again with a negative length and the copy, then if the function is called with a negative length, it reverses the first and last inplace, then recursively calls by moving to the next in the array and shrinks the length till there is nothing left to reverse and then the recursive function unwinds
int* reverse(int *array, int arrayLength){
int* result;
if(arrayLength > 0)
{
result =(int*) malloc((sizeof(int)*arrayLength));
memcpy(result, array, sizeof(int)*arrayLength);
reverse(result, -arrayLength);
return result;
}
else if(arrayLength < -1)
{
int end = (-arrayLength)-1;
int temp = array[end];
array[end] = array[0];
array[0] = temp;
return reverse(array+1, arrayLength+2);
}
return array;
}
Considering that arrayLength is always a power of 2. we will apply the function to the two parts of the array then concat them in the reverse way.
Finaly if the array has only one element, we simply return other array with the same element.
int* reverse(int *array, int arrayLength){
int * newArray = NULL;
if(arrayLength == 1){
newArray = (int *)malloc(sizeof(int));
*newArray = array[0];
} else if(arrayLength == 2){
newArray = (int *)malloc(2 * sizeof(int));
newArray[0] = array[1];
newArray[1] = array[0];
} else {
// apply to first half
int * first = reverse(array, arrayLength / 2);
// apply to second half
int * second = reverse(array + arrayLength / 2, arrayLength / 2);
// allocate space
newArray = (int *) malloc(arrayLength * sizeof(int));
// copy parts in reverse way
memcpy(newArray, second, arrayLength / 2 * sizeof(int));
memcpy(newArray + arrayLength / 2, first, arrayLength / 2 * sizeof(int));
// free allocated space for parts
free(first);
free(second);
}
return newArray;
}
I'll give it a shot.
Knowing that the array is of length 2^n means that it can be safely halved. We call the function recursively on each half until length is 2. At this point we swap the two integers. Think { 2,1,4,3,6,5,8,7 }. When we come back from that, each half is then merged opposite of where it came from ( { 4,3,2,1,8,7,6,5} ). Rinse and repeat.
#include <stdio.h>
#include <stdlib.h>
int * reverse( int* arr, int length )
{
if ( length == 1 )
{
int *result = malloc( sizeof( arr[0] ) );
result[0] = arr[0];
return result;
}
int * result = 0;
if ( length == 2 )
{
result = malloc( sizeof( arr[0] ) * 2 );
result[0] = arr[1];
result[1] = arr[0];
}
else
{
int half_length = length / 2;
// named correctly
int * right = reverse( arr, half_length );
int * left = reverse( arr + half_length, half_length );
result = malloc( sizeof( arr[0] ) * length );
for ( int i = 0; i < half_length; ++i )
{
result[i] = left[i];
result[ i + half_length ] = right[i];
}
free( right );
free( left );
}
return result;
}
int main( void )
{
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
int length = 8;
int *reversed = reverse( arr, length );
for ( int i = 0; i < length; ++i )
{
printf( "%d %d\n", arr[i], reversed[i] );
}
free( reversed );
return 0;
}
for all integer arrays with more than 2 elements.
The basic idea is to swap elements from both ends untill the number of elements remaining is 1.
int* reverse_array(int* array, int arrayLength)
{
if(arrayLength <2)
{
return NULL;
}
else
{
int *array1 = NULL;
int *array2 = NULL;
array1 = malloc(arrayLength*sizeof(int));
memcpy(array1,array,arrayLength*sizeof(int));
/*swap the start and end*/
swap(array1,(array1+arrayLength-1));
/* swap the next pair */
array2 = reverse_array(array1+1,arrayLength-2);
memcpy(array1+1,array2,(arrayLength-2)*sizeof(int));
if(array2!= NULL)
{
free(array2);
}
return array1;
}
}

Resources