I'm trying to write a sorting function with just recursion. I keep getting the error:
lvalue required as unary '&' operand
This are the functions I'm using:
void sorter_rec (int a[], int n) {
if (n ==1 ) return;
else {
swap( &(maximumrec(a,n)), &a[n-1]);
sorter_rec(a,n-1);
return;
};
}
The error is in sorter_rec.
void swap(int *px, int *py)
{ int z = *px;
*px = *py;
*py = z;
return;
}
int maximumrec(int ar[], int n)
{
if (n == 1) {
return ar[0];
} else {
int max = maximumrec(ar, n-1);
return ar[n-1] > max ? ar[n-1] : max;
}
}
How can I solve this?
You may not apply the operator & to the temporary object returned by the function maximumrec.
Also if you are using the selection sort starting from the end of array then the maximum element should be also searched starting from the end of array. In this case the sorting algorithm will be more stable.
Here is a demonstrative program that uses your approach but instead of the searching maximum element it searches minimum element. You can rewrite it such a way that it would search the maximum element if you want.
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#define N 20
int * min_element( int a[], size_t n )
{
int *min = a;
if ( !( n < 2 ) )
{
min = min_element( a + 1, n - 1 );
min = *min < *a ? min : a;
}
return min;
}
void swap( int *a, int *b )
{
int tmp = *a;
*a = *b;
*b = tmp;
}
void sort( int a[], size_t n )
{
if ( !( n < 2 ) )
{
int *min = min_element( a, n );
if ( min != a ) swap( a, min );
sort( a + 1, n - 1 );
}
}
int main(void)
{
int a[N];
srand( ( unsigned int )time( NULL ) );
for ( size_t i = 0; i < N; i++ ) a[i] = rand() % N;
for ( size_t i = 0; i < N; i++ ) printf( "%d ", a[i] );
printf( "\n" );
sort( a, N );
for ( size_t i = 0; i < N; i++ ) printf( "%d ", a[i] );
printf( "\n" );
return 0;
}
The program output might look like
17 9 12 15 1 17 19 17 6 2 14 19 2 8 5 19 0 12 16 8
0 1 2 2 5 6 8 8 9 12 12 14 15 16 17 17 17 19 19 19
Your basic algorithm works. All I had to do was fix up the way you passed pointers around, and it worked the first time! Hope this helps. I changed some names to fit my own style a bit, and added some convenience things (macro and logging method), and main() so I could test it.
Note that the name of an array is the same as &array[0]
#include <stdio.h>
#define INT_COUNT(n) (sizeof(n) / sizeof(int))
void dumpIntArray(int *array, int n) {
printf("{ ");
for (int i = 0; i < n; i++) {
printf("%d ", array[i]);
}
printf(" }\n");
}
void swap(int *px, int *py) {
int z = *px;
*px = *py;
*py = z;
return;
}
int *ptrToMax(int *sortable, int n) {
if (n == 1) {
return sortable;
} else {
int *maximum = ptrToMax(sortable, n - 1);
return sortable[n - 1] > *maximum ? &sortable[n - 1] : maximum;
}
}
void quicksort(int *sortable, int n) {
if (n == 1 ) {
return;
} else {
swap(ptrToMax(sortable, n), &sortable[n - 1]);
quicksort(sortable, n - 1);
return;
}
}
int main(int argc, char **argv) {
int foo[] = { 1, 5, 3, 2, 4, 9, 10, 8, 7 };
printf("Before:\n");
dumpIntArray(foo, INT_COUNT(foo));
quicksort(foo, INT_COUNT(foo));
printf("After:\n");
dumpIntArray(foo, INT_COUNT(foo));
}
Related
I'm trying to find the index of the biggest number in array, by using a recursive function, but it doesn't work for me.
I wrote this code in "Online C Complier":
#include <stdio.h>
int max(int arr[], int n){
if (n==0) {
return 0;
}
int temp = max(arr, n-1);
if (arr[temp] > arr[n]) {
return temp;
}
else {
return n;
}
}
int main()
{
int arr[] = {20,2,44,6,1,15,25,40};
printf("The index is: %d\n", max(arr, 8));
return 0;
}
The out put is sometimes 8 which is wrong and sometimes 2 which is correct.
thanks u all!
For starters the first function parameter should have qualifier const because the passed array is not being changed within the function.
This part of the function
int temp = max(arr, n-1);
if (arr[temp] > arr[n]) {
return temp;
}
else {
return n;
}
is incorrect. For example n is not a valid index.
The function can look the following way as shown in the demonstration program below.
#include <stdio.h>
size_t max( const int arr[], size_t n )
{
if ( n > 1 )
{
size_t i = max( arr + 1, n - 1 ) + 1;
return arr[0] < arr[i] ? i : 0;
}
else
{
return 0;
}
}
int main( void )
{
int arr[] = { 20, 2, 44, 6, 1, 15, 25, 40 };
const size_t N = sizeof( arr ) / sizeof( *arr );
printf( "The index is: %zu\n", max( arr, N ) );
}
The program output is
The index is: 2
Or using your approach the function can look like
size_t max( const int arr[], size_t n )
{
if ( n > 1 )
{
size_t i = max( arr, n - 1 );
return !( arr[i] < arr[n-1] ) ? i : n - 1;
}
else
{
return 0;
}
}
So this is the code I wrote, trying to reverse that array t using recursivity
#include <stdio.h>
#include <stdlib.h>
void rev(int n, float *t)
{
float x;
if(n==0)
{
return 0 ;
}
else
{
x=*t;
*t=*(t+(n-1));
*(t+(n-1))=x;
return rev(n-1, t+1);
}
}
void main()
{
int i;
float t[]={1,2,3,4,5,6,7,8,9};
int n=sizeof t /sizeof *t;
rev (n,t);
for(i=0;i<n;i++) printf("%f",t[i]);
}
I'd like to understand why this solution does not work, I'm not that interested in the solution overall but I want to understand what mistakes I made in this one for it not to work.
For starters a function that has the return type void shall return nothing value. So this statement
return 0 ;
is invalid.
The function swaps two elements so the size of the array must be decremented by 2.
The function can look like
void rev( float a[], size_t n )
{
if ( !( n < 2 ) )
{
float tmp = *a;
*a = *( a + n - 1 );
*( a + n - 1 ) = tmp;
rev( a + 1, n - 2 );
}
}
and be called like
size_t n = sizeof t /sizeof *t;
rev( t, n);
Here is a demonstrative program.
#include <stdio.h>
void rev( float a[], size_t n )
{
if ( !( n < 2 ) )
{
float tmp = *a;
*a = *( a + n - 1 );
*( a + n - 1 ) = tmp;
rev( a + 1, n - 2 );
}
}
int main(void)
{
float a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
size_t n = sizeof a /sizeof *a;
for ( size_t i = 0; i < n; i++ )
{
printf( "%.0f ", a[i] );
}
putchar( '\n' );
rev( a, n );
for ( size_t i = 0; i < n; i++ )
{
printf( "%.0f ", a[i] );
}
putchar( '\n' );
return 0;
}
The program output is
1 2 3 4 5 6 7 8 9
9 8 7 6 5 4 3 2 1
Pay attention to that according to the C Standard the function main shall be declared like
int main( void )
instead of
void main()
There are small easy to fix problems like return 0; and return rev(n-1, t+1);. The first one should be just
return;
because you can't return anything from a function returning void.
The other should be a call to rev() itself
rev(n-1, t+1);
because that's what recursive functions do (and also because you can't return anything)
Then you should use int main( void ) or at least int main() Difference between int main() and int main(void)?
Finally, you have a logic error here
x=*t;
*t=*(t+(n-1));
*(t+(n-1))=x;
rev(n-1, t+1);
*(t+(n-1)) will always be the value of the last element of the array: yes you pass n-1 so you expect that if *(t+(n-1)) was 8th element, in the next call it will be 7th, however you are also passing t+1 so *(t+(n-1)) will always be the 8th element of the array.
And even this one is an easy-to-fix problem. You just pass n-2.
Here's your recursive function
void rev(int n, float *t)
{
float x;
if(n > 0) {
x=*t;
*t=*(t+(n-1));
*(t+(n-1))=x;
rev(n-2, t+1);
}
return;
}
Doing
if(n != 0) {
.... something....
}
return;
Is the same of doing
if(n == 0) {
return;
}
else {
... something...
}
I put n > 0 instead of n != 0 because since n is always initially positive the two conditions are equivalent, however since you pass n-2 if n is an odd number you are going to have negative values of n without passing for 0.
I have to use the recursive selection sort in order to order different arrays of integers.
These arrays are respectively formed by 100, 1000, 10000, 100000, 200000, 500000 items and can be formed by ordered numbers, partially ordered numbers, inverted ordered numbers and random numbers.
After that I have to calculate the time the algorithm took to order the array.
I have to use recursion, It's a homework.
I created a function that generates the array:
typedef enum {ORINATO, INVERS, PARZ_ORDINATO, RANDOM} Ordine;
int *generaArray(int dimensione, Ordine ordine) {
int i, j, n;
int *array = (int*)malloc(dimensione * sizeof(int));
if (!array){
return NULL;
}
switch (ordine){
case ORINATO:
for (i = 0; i < dimensione; i++){
array[i] = i;
} break;
case INVERS:
n =0;
for ( i = dimensione-1; i >= 0 ; i--) {
array[i] = n;
n++;
}break;
case PARZ_ORDINATO:
for (i = 0; i < dimensione/2 ; i++) {
array[i] = i;
}
for (j = i+1; j <dimensione; j++){
n = rand();
array[j] = n;
};break;
case RANDOM:
for ( i = 0; i <= dimensione ; i++) {
array[i] = rand();
}break;
default:
break;
}
return array;
}
And it works like wonders.
Then I have created the recursive selection sort like follows:
void recursiveSelectionSort(int *array, int dim, int start){
int min=0;
if (start >= dim-1){
return;
}
min = findMin(array, start, start+1, dim);
swap(&array[min], &array[start]);
recursiveSelectionSort(array, dim, start+1);
}
int findMin(int *array, int min, int start, int dim){
if(start == dim ){
return min;
}
if (array[start]< array[min]){
min = start;
}
return findMin(array, min, start+1, dim);
}
void swap (int* x, int *y){
int temp = *x;
x = *y;
y = *temp;
}
Now, this as well should work but something clearly isn't. Let's make an example with the implementation, this is what i put in my main:
int main() {
int *array;
clock_t start, end;
double t;
array = generaArray(1000, ORINATO);
start = clock();
recursiveSelectionSort(array, 1000, 0);
end = clock();
t = ((double) (end - start)) / CLOCKS_PER_SEC;
printf("\nIl tempo impiegato per 1000 elementi è: %lf secondi", t);
return 0;
}
This works (but it's slower thank it should be). However if you try and change the dimension from 1000 to 200000 or 500000 it shows error 11.
What is it causing it? I tried everything but it doesn't seem to work.
For starters recursive functions called for large arrays can invoke a stack overflow.
So use non-recursive functions that implement the method selection sort for large arrays.
As for your implementation then for example the function swap has typos.
void swap (int* x, int *y){
int temp = *x;
x = *y;
y = *temp;
}
I think you mean
void swap (int* x, int *y){
int temp = *x;
*x = *y;
*y = temp;
}
All other functions have too many parameters.
For example the function findMin can be declared the following way
size_t findMin( const int *a, size_t n );
and can be also defined as a recursive function (if you decided to write recursive functions then this function can be also recursive)
Here is a demonstrative program that shows how the functions can be defined
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void swap( int *x, int *y )
{
int temp = *x;
*x = *y;
*y = temp;
}
size_t findMin( const int a[], size_t n )
{
if ( n < 2 )
{
return 0;
}
else
{
size_t i = findMin( a + 1, n - 1 ) + 1;
return a[i] < a[0] ? i : 0;
}
}
void recursiveSelectionSort( int a[], size_t n )
{
if ( !( n < 2 ) )
{
size_t i = findMin( a + 1, n - 1 ) + 1;
if ( a[i] < a[0] ) swap( &a[0], &a[i] );
recursiveSelectionSort( a + 1, n - 1 );
}
}
int main(void)
{
enum { N = 15 };
int a[N];
srand( ( unsigned int )time( NULL ) );
for ( size_t i = 0; i < N; i++ )
{
a[i] = rand() % N;
}
for ( size_t i = 0; i < N; i++ )
{
printf( "%d ", a[i] );
}
putchar( '\n' );
recursiveSelectionSort( a, N );
for ( size_t i = 0; i < N; i++ )
{
printf( "%d ", a[i] );
}
putchar( '\n' );
return 0;
}
The program output might look like
11 9 3 5 6 8 2 4 5 3 7 9 2 0 14
0 2 2 3 3 4 5 5 6 7 8 9 9 11 14
I've prepared a code that should found the longer series of elements in growing order .for example ,in arrays exists following elements : 1 2 3 4 5 2 7 6 7 9,output will 5 (the series from 1 to 5) ,function will return integer tempcount that include numbers of element and print it.but get an error ,the function
isn't working:
#include "stdafx.h"
#include <stdio.h>
int find_maximum(int[], int);
int main() {
int c, array[100], size, location, maximum,found;
scanf_s("%d", &size);
for (c = 0; c < size; c++)
scanf_s("%d", &array[c]);
location = find_maximum(array, size);
maximum = found;
printf("Maximum elements = %d ", maximum);
return 0;
}
int find_maximum(int a[], int n) {
int c, index = 0,count =1,tempCount=1;
for (c = 1; c < n; c++)
if (a[c] > a[index])
count +=1;
else
{
if (count > tempCount)
{
tempCount=count;
}
}
return tempCount;
}
The variables maximum and found are not initialized and are used nowhere except this statement that does not make sense
maximum = found;
You are storing the length of the maximum subsequence in the variable location
location = find_maximum(array, size);
It is the variable value which you need to output.
The function find_maximum also does not make sense. For example you are comparing elements of the array with the same element at position 0.
int c, index = 0,count =1,tempCount=1;
^^^^^^^^^
for (c = 1; c < n; c++)
if (a[c] > a[index])
count +=1;
//…
The function can be declared and implemented as it is shown in the demonstrative program below.
#include <stdio.h>
size_t max_ascending_seq( const int a[], size_t n )
{
size_t max_n = 0;
for ( size_t i = 0; i < n; )
{
size_t current_n = 1;
while ( ++i < n && a[i-1] < a[i] ) ++current_n;
if ( max_n < current_n ) max_n = current_n;
}
return max_n;
}
int main(void)
{
int a[] = { 1, 2, 3, 4, 5, 2, 7, 6, 7, 9 };
const size_t N = sizeof( a ) / sizeof( *a );
size_t max_n = max_ascending_seq( a, N );
printf( "%zu\n", max_n );
return 0;
}
The program output is
5
A more generic function can be written the following way.
#include <stdio.h>
size_t max_ascending_seq( const int a[], size_t n, int predicate( int, int ) )
{
size_t max_n = 0;
for ( size_t i = 0; i < n; )
{
size_t current_n = 1;
while ( ++i < n && predicate( a[i-1], a[i] ) ) ++current_n;
if ( max_n < current_n ) max_n = current_n;
}
return max_n;
}
int less_than( int x, int y )
{
return x < y;
}
int greater_than( int x, int y )
{
return y < x;
}
int main(void)
{
int a[] = { 1, 2, 3, 4, 5, 2, 7, 6, 7, 9 };
const size_t N = sizeof( a ) / sizeof( *a );
size_t max_n = max_ascending_seq( a, N, less_than );
printf( "%zu\n", max_n );
max_n = max_ascending_seq( a, N, greater_than );
printf( "%zu\n", max_n );
return 0;
}
The program output is
5
2
I am trying to write a recursion function that takes an array as an argument and returns the MIN and MAX values. So far i can only get MAX. I tried to add a pointer to send back the minimum value but for some reason, it always crashes and shows lots of warnings.
Please help me figure out what is wrong in my code.
int MinMaxArray(int arr[], int size, int* min)
{
if (size == 1)
return arr[0];
if (arr[size - 1] > MinMaxArray(arr, (size - 1), &min))
return arr[size - 1];
else
return MinMaxArray(arr, (size - 1), &min);
}
so i tried this but the min that return is allways the one in index 0
how to make it works?
int MinMaxArray(int arr[], int size, int* min)
{
if (size == 1)
{
*min = arr[0];
return arr[0];
}
if (arr[size - 1] < MinMaxArray(arr, (size - 1), min))
*min = arr[size - 1];
else
*min = MinMaxArray(arr, (size - 1), min);
if (arr[size - 1] > MinMaxArray(arr, (size - 1), min))
return arr[size - 1];
else
return MinMaxArray(arr, (size - 1), min);
}
like this
#include <stdio.h>
#include <assert.h>
int MinMaxArray(int arr[], int size, int *min){
assert(arr != NULL && size > 0);
if (size == 1){
*min = arr[0];
return arr[0];
}
int max = MinMaxArray(arr, size - 1, min);
if (arr[size - 1] < *min)
*min = arr[size - 1];
return (arr[size - 1] > max) ? arr[size - 1] : max;
}
int main(void) {
int arr[] = { 1,5,9,2,6,-4,8,3,7 };
int min, max = MinMaxArray(arr, sizeof(arr)/sizeof(*arr), &min);
printf("max:%d, min:%d\n", max, min);
return 0;
}
The third argument specified for the call
MinMaxArray(arr, (size - 1), &min)
has wrong type relative to the parameter declaration.
The argument has type int ** while the parameter has type int *.
Also the minimum element is not calculated.
In C++ there is standard algorithm named minmax_element that returns a pair of pointers that point to the maximum an minimum elements of an array.
You could use a similar declaration of the function written in C.
Another approach is to return a pair of indices of the minimum and maximum elements.
To do so you need to declare a structure of two data members.
Below there is shown how the function that returns a pair of indices can be implemented in C.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
struct MinMax
{
size_t min;
size_t max;
};
struct MinMax minmax_element( const int a[], size_t n )
{
struct MinMax minmax = { 0, 0 };
if ( n > 1 )
{
struct MinMax current = minmax_element( a + 1, n - 1 );
++current.min; ++current.max;
if ( a[current.min] < a[minmax.min] ) minmax.min = current.min;
if ( a[minmax.max] < a[current.max] ) minmax.max = current.max;
}
return minmax;
}
#define N 10
int main(void)
{
int a[N];
srand( ( unsigned int )time(NULL ) );
for ( size_t i = 0; i < N; i++ ) a[i]= rand() % ( 2 * N );
for ( size_t i = 0; i < N; i++ ) printf( "%d ", a[i] );
putchar( '\n' );
struct MinMax minmax = minmax_element( a, N );
printf( "The minimum is %d\n", a[minmax.min] );
printf( "The maximum is %d\n", a[minmax.max] );
return 0;
}
Its output might look like
14 6 7 9 6 7 15 12 0 10
The minimum is 0
The maximum is 15
Take into account that the user can pass to the function an "empty" array that is when the argument that corresponds to the size of the array is equal to 0. In this case your own function implementation has undefined behavior.
If you may not use a structure then the function can be declared like
void minmax_element( const int a[], size_t n, size_t *min, size_t *max );
Or
void minmax_element( const int a[], size_t n, int **min, int **max );
It will not be difficult to change the shown above recursive function according to these declarations.
For example
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void minmax_element( const int a[], size_t n, size_t *min, size_t *max )
{
*min = 0;
*max = 0;
if ( n > 1 )
{
size_t cur_min, cur_max;
minmax_element( a + 1, n - 1, &cur_min, &cur_max );
++cur_min; ++cur_max;
if ( a[cur_min] < a[*min] ) *min = cur_min;
if ( a[*max] < a[cur_max] ) *max = cur_max;
}
}
#define N 10
int main(void)
{
int a[N];
srand( ( unsigned int )time(NULL ) );
for ( size_t i = 0; i < N; i++ ) a[i]= rand() % ( 2 * N );
for ( size_t i = 0; i < N; i++ ) printf( "%d ", a[i] );
putchar( '\n' );
size_t min;
size_t max;
minmax_element( a, N, &min, &max );
printf( "The minimum is %d\n", a[min] );
printf( "The maximum is %d\n", a[max] );
return 0;
}