Question about a recursive function? - c

I have a recursive function from a C book as follows:
void print(int a[], int n)
{ if (n<=0) return ;
printf("%d\n", a[0]);
print(&a[1], n-1);
}
I have run and this function prints all the element of the specified array. But I really do not understand how this function works so that I can print all elements of an array.
Can anyone give me a clear explanation, please?

&a[1] is the address of the second element of the array, which is effectively the address of the portion of the array after the first element. So after printing the first element of the parameter array,
print(&a[1], n-1);
passes itself the remaining portion of the array, decreasing the length by one as well.
For example, if you call print with the array {1, 2, 3, 4, 5} and n == 5, the chain of events and calls is the following:
print the first element (1)
call itself with the remaining portion of the array, i.e. {2, 3, 4, 5} and n == 4
print the first element (2)
call itself with the remaining portion of the array, i.e. {3, 4, 5} and n == 3
print the first element (3)
call itself with the remaining portion of the array, i.e. {4, 5} and n == 2
print the first element (4)
call itself with the remaining portion of the array, i.e. {5} and n == 1
print the first element (5)
call itself with the remaining portion of the array, i.e. {} and n == 0
n<=0 -> return
return
return
return
return
return

This function takes as arguments the remaining part of the array and how many elements it contains. Every time you print the first element and then call recursively of the remaining part. Here is an example:
array: 1, 2, 3, 4, 5, 6; N = 6
array: 2, 3, 4, 5, 6; N = 5
array: 3, 4, 5, 6; N = 4
array: 4, 5, 6; N = 3
array: 5, 6; N = 2
array: 6; N = 1
array: ; N = 0 return;

Arrays are basically pointers to the start of the first element, so you code is essentially this:
void print(int *a, int n)
{ if (n<=0) return ;
printf("%d\n", *a);
print(a+1, n-1);
}
The recursive call is passing in a pointer to the next item in the array and decreasing the count, which is your used in your recursive termination condition.

So it does the following:
Check if there are any elements in the array, if not, just return.
Print the first element in the array since we know we have atleast one.
Calls itself again pointing to the 2nd element in the array, and subtracting 1 from the size, thus starting at #1 again.

A good way to understand recursion IMHO is to run the code in a debugger, and watch the call stack and variables.

How do you print a zero-sized array? Easy: you don't
That's your if (n<=0) return;
How do you print an array with 1 element? Easy: just print the element and remove it from the array and print the resulting zero-sized array as before
That's your printf("%d\n", a[0]);
How do you print an array with 2 elements? Easy: print the first element and remove it from the array and print the resulting one-sized array as before
That's your print(&a[1], n-1);
How do you print an array with N elements?
Easy: print the first element, remove it from the array, and print the resulting smaller array

If n is zero (or less), it does nothing, so recursion stops. If n > 0, then it prints a[0] and calls itself recursively with n-1 for n (so that goes to 0 as the recursion proceeds) and &a[1] for a, i.e. it increments the pointer a in each recursive call. Remember that an array argument in C is syntactic sugar for a pointer argument.
So, the code you posted is equivalent to:
void print(int *a, int n)
{
if (n > 0) {
printf("%d\n", *a);
print(a+1, n-1);
}
}

If you can verify to yourself that the following algorithm works to print an array, you should be able to understand why the C code works, since it's a direct translation.
To print n elements of an array:
If you're asked to print no elements, just stop.
Otherwise:
Print the first element, and then
Print n-1 elements of the rest of the array (using this same recipe).

it is equivalent to a loop:
int i ;
for (i = 0 ; i< n ; i++) {
printf("%d\n",a[i]);
}
why? well, the recursion always looks at the first element and prints it, and them advances to the next element by looking at the array from the 2nd element (which will now be the 'first', in the next iteration).
your stop condition is when no more elements are left - i.e. an array of length 0.

The function accepts an array and the length of the array.
if(n<=0) return;
If the length of the array is <=0 the function returns.
printf("%d\n", a[0]);
The first element of the array, element 0 is printed.
print(&a[1], n-1);
&a[1] gets a pointer to the first element of the array. Arrays and pointers are usable interchangably so when this is passed to the function the function can treat it as a new array, starting from the second element of the previous array, and with a length one less.

Each call to print do this :
print the n-th element of the array a and decrement the remaining elements (n) count to print.(Look at n like it means: how many elements remain to print).
Call it self decrementing (n - 1 : one less element to print) passing a pointer to the second element of the array (&a[1]) because the first element (a[0])has already be printed.
What exactly don't you understand?

Related

Counting Sort issue in array

I am making an algorithm for counting sort. In first step i have initialized the second array with 0. Secondly i counted the frequency of elements in second for loop. In third loop i am trying to sort the array. The third loop does not run in code blocks. Also it's not giving me right sorted result.Any issue with third loop. As it changes array to 1-1-2-0-2-2-0-1-1 rather it should be 0-0-0-1-1-1-1-2-2-2
printf("Hello world!\n");
unsigned m=3;
unsigned n=10;
unsigned x;
unsigned k;
unsigned data[10] = {0, 2, 1, 1, 0, 2, 2, 0, 1, 1};
unsigned *count;
count =(unsigned *)malloc(sizeof(unsigned)*m);
int y=sizeof(data);
for(int i=0;i<m;i++)
{
count[i]=0;
}
for(int j=0;j<n;j++)
{
x=data[j];
count[x]++;
}
for(k=n-1;k>=0;k--)
{
data[count[data[k]]-1]=data[k];
count[data[k]]=count[data[k]]-1;
}
for(int i=0;i<n;i++)
{
printf("%d \n",data[i]);
}
return 0;
}
In this line
for(k=n-1;k>=0;k--)
k is unsigned so k >= 0 is always true. When an unsigned integer would go below zero, its value "wraps".
Also, your sorting loop does not sort anything. It can't because there are no comparisons. You may like to review your algorithm.
The problem (in addition to the loop condition error mentioned in another answer) is that this appears to be a combination of two incompatible counting sort approaches.
The "traverse the input array backwards, inserting each element into the appropriate place in the output array" approach requires a separate output array. Consider the simple case of sorting {2, 1}: if we copy the 1 into the appropriate slot in the same array, it becomes {1, 1}, which will end up being our final output. Instead, that 1 needs to be placed into the appropriate slot of a separate array so that we don't overwrite the 2.
Additionally, this approach requires us to make a second pass over the count array to change its semantic meaning from "count of elements with value n" to "index of first element with value > n". This is accomplished by adding the total so far to each element of count (so in your case, count would go from {3, 4, 3} to {3, 7, 10}). After this step, count[n] - 1 is the index in the output array at which the next n should be placed.
Given that you're sorting integers, a second (easier) approach is also possible: once you've finished your initial traversal of the input array, count holds all the information you need, so you can freely overwrite the input array. Just start at the beginning and insert count[0] 0s, count[1] 1s, etc. This approach doesn't require any postprocessing of count or any separate output array.

Passing an array into a function in C

Consider the following C program:
#include <stdio.h>
void swap(int []);
int main(void) {
int a[3] = {1, 2, 3};
swap(a);
printf("%d %d %d\n", a[0], a[1], a[2]);
swap(&a[1]);
printf("%d %d %d\n", a[0], a[1], a[2]);
return 0;
}
void swap(int x[]) {
int temp = x[0];
x[0] = x[1];
x[1] = temp;
}
Can anyone explain why the following code gives an output
2 1 3
2 3 1
rather than
2 1 3
1 2 3
I understand that swap(a) swaps a[0] and a[1]. But I'm not so sure how swap(&a[1]) works. In both cases we are passing the array a into the function swap, are we not? So my hypothesis was that swap(&a[1]) should again swap a[0] and a[1], giving us back the original order 2 3 1.
EDIT: This code was written as intended. I just wanted to see what happens if we pass an address of an element other than the first element into the function. Apparently if I pass &a[n] into the function, it disregards all elements before a[n] and treats a[n] as the first element?
Your swap function takes and address of an integer as input and swaps element at that address with element at next address.
swap(a) is same as swap(&a[0])
It will swap element at index 0 with element at index 1.
Now your array becomes {2,1,3}
swap(&a[1]) swaps element at index 1 with element at index 2.
So your array now becomes {2,3,1}
Remember when you pass an array actually you are passing address of element at index 0 (&a[0]).
Because when you swap first time you sent an array starting with 0 index then it exchanges 0th and 1st index values means at first swap, array becomes {2,1,3} then again you sent this array starting with 1 index means you sent only two values {1,3}, then that values gets exchanges. In this case x[0] = 1 & x[1] = 3, that is why the output came as {2,3,1} here 2 remains as it is.
In the first call swap(a); you are passing the entire array (actually a pointer to the first element.) So you are swapping elements 0 and 1, which are 1 and 2, respectively, therefore your first output is 2 1 3.
In the second call swap(&a[1]); you are passing the address of the second element in the array, and in your swap function you are therefore swapping the second and third elements, at indices 1 and 2, which are 1 and 3, respectively. That's why your answer after the second iteration is 2 3 1.
Possibly what you meant was
swap(&a[0]);
This will swap the values at indices 0 and 1, which will give you the desired output of 1 2 3.
In your code before the first println statement you are passing a complete array to the parameter of the fuction but in the next you are just passing a single value of location of a[1] which make bit confusing for the function because it has only a single value to swap or it might be as first you passed a zero(0) index or the array to swap with the next time you pass first 1 index of array to swap with which means [1,3 to swap] so pass complete in next statment as this
swap(a);
printf("%d %d %d\n", a[0], a[1], a[2]);
swap(a);
printf("%d %d %d\n", a[0], a[1], a[2]);
return 0;
this will generate your desire answer

Strange expression in the return statement

I found a recursive function that left me a little surprised this function counts all negative numbers which appear in an array :
int count_negative(int arr[], int n)
{
if ( n > 0 )
return (*arr < 0) + count_negative( ++arr, n - 1 );
return 0;
}
Can someone explain this line :
return (*arr < 0) + count_negative( ++arr, n-1 );
Thank you
(*arr < 0) compares first element of the array with zero. The result of the expression can be either 1 (first element is negative) or 0 (first element is positive or zero). So, the number of negative elements is the sum of this expression and the number of negative elements in the tail of the array.
*arr points to the first element of arr array (or, more precisely, the part of the arr that has been passed to the function in this particular call).
count_negative( ++arr, n-1 ) is a recursive call but because of ++arr, inside this call we count the next element of the array and n-1 argument, togeher with the if ( n > 0 ) guarantees that we will count only elements inside the arr array.
The principle is that instead of keeping an index on the element being inspected, since arr is a pointer and modifying it will not change the data, one may instead use arr itself as the iterator on the array data.
So, *arr < 0 checks if the current pointed element is negative (it will yield 1 if so, 0 if not), and ++arr increments the cursor to the next place in the array, which is then passed on recursively to check the rest of the array.
This is a very well known idea in functional languages working with lists, where you often work on the first element of the list (the head) and recurse on the remaining of the list (the tail).

Why is this code for implementing mergesort not producing correct result?

Here in I'm trying to implement mergesort on array of 10 elements. On providing the input a[10]={9,8,7,6,5,4,3,2,1,0} , I obtain the output as {0,0,1,1,0, 4,4,4,3,2} while the expected output is {0,1,2,3,4,5,6,7,8,9}. I am calling the mergesort in main with l=0,h=9.
void mergesort(int a[],int l,int h)
{
int c[10];
int m=(l+h)/2;
if(l<h)
{
mergesort(a,l,m); // Recursive call to sort first half
mergesort(a,m+1,h); // Recursive call to sort second half
}
int i,k=l,j=l;
while(k<=h) // Merging the first and second half of the array
{
if(a[j]<a[m+1])
{
c[k]=a[j];
k++;
j++;
}
else
{
c[k]=a[m+1];
k++;
m++;
}
}
for(i=l;i<=h;i++)
a[i]=c[i];
}
One of the few problems: Your value of l is no longer a valid left limit after the while loop since you are incrementing it. So when you are copying from array c to a later in the for loop, you are copying invalid data.
The problem is that in your while loop you are sometimes looking outside the bounds you should be.
Assuming you put in a check at the beginning of your function saying if l==h then return (since sorting a one element array is unnecessary) then the first time it will do anything is when it recurses to mergesort(a, 0,1). Here we are basically merging two single element arrays.
When going through your loop the first time we have i,j,k,m=0. We will go into the else part of the if because element 0 is greater than 1. We thus write out a[1] into the output array and we now have i,j=0 and k,m=1. What we now should do is note that our second array is exhausted and fill from the remaining elements in the first array.
Instead what we do is compare elements j and m+1 (ie 0 and 2). This is clearly wrong because element 2 shouldn't appear in the array. We of course find element 2 is smaller and thus put that into the output array at position two. Once we copy this over a we get {8, 7, 7, 6, 5, 4, 3, 2, 1, 0} and this is where it all goes wrong.

What does ++ do after the array in this function?

void doSomething()
{
int hist[5] = { 0 };
int num_bins = 5;
int indices[10] = { 0, 0, 2, 3, 3, 3, 3, 4, 4, 4 };
int num_indices = 10;
int i;
for (i = 0; i < num_indices; i++)
{
hist[indices[i]]++;
}
for (i = 0; i < num_bins; i++)
{
printf("%d ", hist[i]);
}
printf("\n");
}
Assume I have correct libraries this is a conceptual question from class. I am wondering how the answer comes out to 2 0 1 4 3 for the array.
The line
hist[indices[i]]++
Says "go to the element of the hist array at index indices[i], then increment it." If you think of the array as a list of counters, this says to increment the counter at position indices[i].
This code builds a histogram of the frequencies of various numbers in an array. The idea behind the above code is to iterate over the array and increment the frequencies of each element.
Hope this helps!
The elements in indices range from 0 to 4, which are all valid index of the 5 elements array hist. (That's why the array is named indices, as it's for indexing)
So for instance, i is 2, then indices[i] is 2.
hist[indices[i]]++;
is equivalent to
hist[2]++;
For small questions like this you should try to write down the state of every element of each array on a piece of paper and execute your code step by step. You could also write the code to print useful information in runtime.
If after that you still can't figure it out then it's worth asking here. Otherwise you won't be learning much.
This program increments the 0's in
hist
as it indexes appear in
indices[10]
eg.
when you have the first for interation
hist[indices[0]]++ // hist[0]++ --> 0++;
It looks like "2 0 1 4 3" is a count of how many items exists in the array. 2 0's, 0 1's, 1 2, 4 3's and 3 4's. So the query is counting how many instances of each number are in the array and then printing out that result.
So the statement:
hist[indices[i]]++
find the value of indices[], then increments the int in the hist[] array by 1 giving you a count of how many of those elements are in the array.
1.As you have partially initialized your array, compiler sets other values to 0
2.hist[indices[i]]++; this statement increments the value of hist[i], for the current value of i
3.the value of i is denoted by your array indices[]
4.try having values grater than 5 in your array named indices[].

Resources