Consider this code, which computes the maximum element of an array.
#include <stdio.h>
int maximum(int arr[], int n)
{
if (n == 1) {
return arr[0];
} else {
int max = maximum(arr, n-1);
printf("Largest element : %d\n", max);
return 5; // return arr[n-1] > max ? arr[n-1] : max;
}
}
int main()
{
int array[5] = {5, 23, 28, 7, 1};
printf("Maximum element of the array is: %d", maximum(array, 5));
return 0;
}
Why is the else block called four (4) times?
The function is recursive, thus it will be called multiple times.
When you first start, n=5. It will take the else block (n is not 1).
Then, you call maximum again with n-1 (n=4). Again, the else block is taken.
All told, the function is called 4 times before n reaches 1, whereupon it takes the if block and returns ar[0].
As others have mentioned, the function as written will not return the maximum value of the list. Curiously, it seems to always return 5 unless the list array size is 1, in which case it returns the value of that element.
Instead, a recursive approach would typically involve splitting the list in half each time, then returning the max of each pair when the list finally broken into pairs of elements.
That is what it is coded to do...
Take a look:
from main we call maximum with 5, then in the else we call the function again with n-1.
maximum(array, 5) //first call from main, hit the else n=5, so recall with n-1
maximum(ar, 4) //second call from maximum, hit the else n=4, so recall with n-1
maximum(ar, 3) //third call from maximum, hit the else n=3, so recall with n-1
maximum(ar, 2) //fourth call from maximum, hit the else n=2, so recall with n-1
maximum(ar, 1) //fifth call from maximum, n==1 now so do the if and return 5
A possible recursive solution is to compare the previous and the current element.
#include <stddef.h>
static int max(int a, int b) {
return a > b ? a : b;
}
int max_array(int *p, size_t size)
{
if (size > 1) return max(p[size-1], max_array(p, size-1));
else return *p;
}
Actually it is called only 4 times.
The recursion rule, as you declared it is:
if n==1, return ar[0] else return the maximum of n-1 elements.
So, the else part is being called for 5, 4, 3 and 2.
However, this recursion is not good enough. As your function is called n-1 times, you only pay the overhead of recursion (stack for example) but you get no advantage over iteration.
If you really want recursion for this task, try to divide the array to 2 and pass each half to the recursive function.
simple pseudo code (not handling odd numbers correctly):
int max(int arr[], int n)
{
if (n<=1)
return arr[0];
return MAX(max(arr, n/2), max(arr+n/2, n/2));
}
int maximum(int ar[], int n)
{
int max;
if(!n)
return ar[n];
max =maximum(ar,n-1);
return ar[n]>max?ar[n]:max;
}
Related
I currently finished my code. but for some reason my recursive call at the end isn't being triggered? Is there some sort of special code I am missing from this by chance?
int max(int arr[], int start, int end) {
int greatest = arr[start];
if(start < end)
{
if(greatest<arr[start])
{
greatest = arr[start];
}
start++;
max(arr, start, end); // Doesn't seem to be triggering since it only returns 8
}
return greatest;
}
int main()
{
int greatest;
int arr[10] = {8,1,2,3,4,5,6,7,8,9};
int start = 0;
int end = 10;
greatest=max(arr, start, end);
pintf("%d\n", greatest);
}
Only the first call to max - the one located in main - actually assigns its return value to anything. The values returned by the recursive calls are immediately lost; the work they do is meaningless to the end result. You need to assign the result of the recursive call to max to greatest.
Remember that each recursive call opens up a new scope, each with its own version of the greatest variable. The assignments within each recursive call only modify their version of the variable, not the one from the enclosing scope; this means that the version from the very first call is never set to anything after taking the value of arr[0]; and that's the version whose value is returned to main when the outermost call resumes, regardless of the work done in between by the recursive calls.
You also have an unrelated error, which is that you recurse into another call to max (and assign to greatest within that call) before checking whether you've reached the end of the array, which will overflow beyond the end of the array and overwrite the final result with whatever is found there (as Paul points out, you also assign to greatest before making the comparison against the current value, so the comparison is essentially meaningless). You need to move everything inside the checks to make sure this doesn't occur.
Your algorithm is a little messed up. For instance, greatest<arr[start] will never be true, because you just set greatest = arr[start]. Here's a commented working algorithm:
#include <stdio.h>
int max(int arr[], int start, int end)
{
if ( start >= end ) {
/* Shouldn't get here, but return 0 if we do */
return 0;
}
else if ( end - start == 1 ) {
/* Only one element, so it's the maximum by definiton */
return arr[start];
}
else {
/* Find the maximum of the rest of the list... */
int greatest = max(arr, start + 1, end);
/* ...and return the greater of it, and the first element */
return arr[start] > greatest ? arr[start] : greatest;
}
}
int main(void)
{
int arr[] = { 8, 1, 2, 3, 12, 5, 6, 7, 8, 9 };
int start = 0;
int end = 10;
int greatest = max(arr, start, end);
printf("%d\n", greatest);
}
with output:
paul#thoth:~/src/sandbox$ ./max
12
paul#thoth:~/src/sandbox$
Let's go through it with a simple list, {1, 5, 3}. Each indentation level represents one of your recursive function calls. Every time we see max(), we go up a level - every time we see return, we go back a level.
In main(), int greatest = max(list, 0, 3)
In call 1: (end - start == 1) is false
In call 1: int greatest = max(list, 1, 3)
In call 2: (end - start == 1) is false
In call 2: int greatest = max(list, 2, 3)
In call 3: (end - start == 1) is true
In call 3: return arr[2], which is 3
Back in call 2: greatest now equals 3
Back in call 2: arr[1] == 5, which is > 3, so return arr[1], which is 5
Back in call 1: greatest now equals 5
Back in call 1: arr[0] == 1, which is not > 5, so return greatest, which is 5
Back in main(), greatest now equals 5
Remember, every time you see int greatest, that's a different variable that's being created. They all have the same name, but since they're all in separate scopes, they're still all different. The int greatest in call 2, for instance, is completely separate from the int greatest in call 1, just as the int greatest in call 1 is completely separate from the int greatest in main().
EDIT: From the comments, if you want the index of the maximum value as well, this'll do it:
#include <stdio.h>
int max_index(int arr[], int start, int end)
{
if ( start >= end ) {
return 0;
}
else if ( end - start == 1 ) {
return start;
}
else {
int greatest = max_index(arr, start + 1, end);
return arr[start] > arr[greatest] ? start : greatest;
}
}
int max(int arr[], int start, int end)
{
if ( start >= end ) {
/* Shouldn't get here, but return 0 if we do */
return 0;
}
else if ( end - start == 1 ) {
/* Only one element, so it's the maximum by definiton */
return arr[start];
}
else {
/* Find the maximum of the rest of the list... */
int greatest = max(arr, start + 1, end);
/* ...and return the greater of it, and the first element */
return arr[start] > greatest ? arr[start] : greatest;
}
}
int main(void)
{
int arr[] = { 8, 1, 2, 3, 12, 5, 6, 7, 8, 9 };
int start = 0;
int end = 10;
int greatest = max(arr, start, end);
int index = max_index(arr, start, end);
printf("Greatest value is %d at index %d\n", greatest, index);
}
output:
paul#thoth:~/src/sandbox$ ./max
Greatest value is 12 at index 4
paul#thoth:~/src/sandbox$
I believe the recursive call is being triggered, but isn't doing what you want. you initialize greatest to arr[start] (in this case 8), and never assign anything else to it, so of course your function is returning 8. Instead, it seems like your function should return arr[start] if start >= end, and otherwise should return either arr[start] or max(arr, start+1, end), whichever is larger.
i've been stuck for hours trying to figure how can i write a function that gets and array of integers, and finds the length of the longest ascending sub-series in the array using recursion and no loops at all. im only allowed to use another 1 recursive function
for example, for the following array: {45,1,21,3,3,6,53,9,18} the outpot should be 5, because the longest sub-series is {1,3,6,9,18}.
So, basicly, a function that gets an array and its size, and needs to print the length of the longest sub-series using no loops at all, no global/static types, and it may use another "help" recursive function and thats it.
this is pretty much all i came up with, and its a mess and not working well.
I'm trying to scan the array while at all time i know the current index im looking at, the index that is being compared to the current, and the originla index from which i started the current sub-series.
I tried to scan the array while knowing the indexes that should be compared but i got stuck, here's what i got, i would really appreciate any tips and advices.
thanks.
void max_set(int arr[], int size)
{
int bigSeries[2] = { 0 };
calcSeries(arr, bigSeries,0, 0, 1, size -1, 1);
printf("number of max parts going up %d \n", bigSeries[0]);
}
void calcSeries(int arr[], int bigSeries[],int originalCHeckedIndex, int checkedIndex, int currentIndex, int lastIndex, int ascending)
{
if ((checkedIndex == lastIndex) || (currentIndex > lastIndex))
{
if (ascending > bigSeries[0])
bigSeries[0] = ascending;
if (originalCHeckedIndex == lastIndex)
return;
else
{
calcSeries(arr, bigSeries, originalCHeckedIndex + 1, originalCHeckedIndex + 1, originalCHeckedIndex + 2, lastIndex, 0);
return;
}
}
if (arr[currentIndex] > arr[checkedIndex])
{
calcSeries(arr, bigSeries, originalCHeckedIndex, currentIndex, currentIndex + 1, lastIndex, ascending + 1);
}
else
{
if (arr[originalCHeckedIndex] < arr[currentIndex])
calcSeries(arr, bigSeries, currentIndex, currentIndex, currentIndex + 1, lastIndex,ascending);
calcSeries(arr, bigSeries, originalCHeckedIndex, checkedIndex, currentIndex + 1, lastIndex, ascending);
}
}
The algorithm has many similarities with the one of first answer, yet covering a few corner cases you might want to watch out. Instead of writing a lengthy comment, I chose to write a new answer instead.
Sanity Checks
Do some sanity checks on the array, as I did in function max_set().
Is an array supplied at all (check for NULL)?
Is the supplied array size at least positive (consider size_t)?
Allowed Values
Data type int allows positive and negative values. The algorithm should handle both. At least I didn't read from your post that they have to be positive. My code looks a bit nicer if you skip that part.
Recursion
The idea of this algorithm (and the one from first answer) is to recursively walk through the array, beginning at the first element, ending at last. So this already defines the start and end of recursion, as documented in source code.
To find the longest sub-series of numbers this way, there are always three possibilities:
The longest sub-series can be reached by skipping the number that is currently processed
The longest sub-series can be reached by adding the number that is currently processed
The currently processed number cannot fit in
A number can be added if it's larger than the largest previously added number; we look for an ascending series after all. The current number could be larger than others in the array that have to be processed, yet. So we have to take both possibilities into account: continuing recursive steps without it and with it -- as long as it fits criteria.
Possible oversight
Take into account that INT_MIN, the smallest possible int value on the machine, is a perfectly valid number in the array. I have added the variable seen, which just records if INT_MIN has been seen at least once in the array or not. On first encounter, seen flips from 0 to 1, not allowing any further INT_MIN values due to requirement of ascending sub-series. Your example shows this requirement with two occurences of number 3.
Tests
Try to find various test cases, and think out of the box at times. NULL for array, negative size, empty array. Next, add fancy values like negative numbers, INT_MIN. Or create ascending series, descending ones, interlacing. Numbers occuring multiple times ...
#include <sys/limits.h>
#include <stdio.h>
int
analyze(int arr[], int size, int min, int seen)
{
int sub_count = 0, count = 0;
/* end of recursion */
if (size == 0)
return 0;
/* recursion step, without and with current number */
sub_count = analyze(arr + 1, size - 1, min, seen);
if (arr[0] > min || (min == INT_MIN && arr[0] == INT_MIN && !seen))
count = 1 + analyze(arr + 1, size - 1, arr[0], arr[0] == INT_MIN);
/* return length of largest sub-series */
return sub_count > count ? sub_count : count;
}
void
max_set(int arr[], int size)
{
int seq = 0;
if (arr != NULL && size > 0) {
/* start of recursion */
seq = analyze(arr, size, INT_MIN, 0);
}
printf("max sequence is %d\n", seq);
}
int
main(void)
{
int arr[] = { 45, 1, 21, 3, 3, 6, 53, 9, 18 };
max_set(arr, sizeof(arr) / sizeof(*arr));
return (0);
}
#include <stdio.h>
int calcSeries(int arr[], int size, int value, int count){
int self, skip, rest;
if(0 == size)
return count;
skip = calcSeries(arr + 1, size-1, value, count);//case of skip the top(self)
if(value < *arr){
self = calcSeries(arr + 1, size-1, *arr, count+1);//case of include top
if(skip > self)
self = skip;
} else
self = skip;
rest = calcSeries(arr + 1, size-1, -1, 0);
return self > rest ? self : rest;
}
void max_set(int arr[], int size){
printf("number of max parts going up %d \n", calcSeries(arr, size, -1, 0));
}
int main(void){
int array[]={45,1,21,3,3,6,53,9,18};
max_set(array, sizeof(array)/sizeof(*array));
return 0;
}
`/* finding the minimum number of a array */
#include<stdio.h>
int minimum(int n, int a[n], int x);
int main(void)
{
int a[5] = { 5, 4, 3, 4, 5 };
printf("%d \n", minimum(4, a, 0));
return 0;
}
int minimum(int n, int a[n], int x)
{
int minima;
if (x >= n)
return a[x];
else
minima = minimum(n, a, x + 1);
if (a[x] > minima)
return minima;
}
`
Hey I read few recursion sources in stackoverflaw. Also found same kind problem using JAVA. Can you please explain me how this code works.Or is this a good coding. I make it my self to learn recursion and it is working.Please explain.
There are two problems in your code:
The termination happens too late: you return a[x] when x==n - that's one element past the end.
There is a missing return when a[x] > minima is false: your function ends without returning a[x].
To fix these two problems, change the check of the termination condition, and add the missing return:
if(x >= n-1) return a[n-1];
// You do not need an else after a return
minima = minimum(n,a,x+1);
if (a[x] > minima) return minima;
return a[x];
Note that you can save one parameter by starting the search at the end of the array and going backward until you reach index zero.
I wrote a program to find the largest number in an array. The problem is that every time the find_largest function is called recursively, the largest variable seems to be filled with garbage from somewhere else in memory. I've stepped through it with a debugger and it seems to be working fine until the recursive call. The pointers for the array and the update to largest, if applicable, show expected values.
/*This program will find the largest integer in an array. It was written to practice
using recursion.*/
#include <stdio.h>
void find_largest(int *a, int n);
int main() {
int a[] = {10, 27, 101, -8, 16, 93};
int n = 6, i = 0;
printf("Current array: ");
while(i < n) {//print array
printf("%d ", a[i]);
i++;
}
find_largest(a, n);
return 0;
}//end main
//This function will start at the last element, and then step through the array
//in reverse order using pointers.
void find_largest(int *a, int n) { //formulate the size-n problem.
int largest = 0;
if(n == 0) { //find the stopping condition and the corresponding return
printf("\nThe largest number is: %d \n", largest);
}
else { //formulate the size-m problem.
n--; //decrement so that the proper number is added to pointer reference
if(largest <= *(a + n)) //check if element is larger
largest = *(a + n); //if larger, assign to largest
find_largest(a, n); //recursive call
}
}
The program returns zero as the largest integer. Any ideas?
largest isn't shared by all of your recursive calls, each gets its own copy. That means in the base case, you execute this code:
int largest = 0;
if (n == 0) {
printf("\nThe largest number is: %d \n", largest);
}
Where largest will always be 0.
You can make largest static and it will work, though it's a bit of a strange way to go about it. I'd prefer to do something like this:
int find_largest(int *a, int n)
{
int subproblem;
// base case - single element array, just return that element
if (n == 1)
{
return *a;
}
// recursion - find the largest number in the rest of the array (increase
// array pointer by one, decrease length by one)
subproblem = find_largest(a + 1, n - 1);
// if the current element is greater than the result of the subproblem,
// the current element is the largest we've found so far - return it.
if (*a > subproblem)
return *a;
// otherwise, return the result of the subproblem
else
return subproblem;
}
largest is initialized to 0 in each separate function call, here's a quick fix:
int find_largest(int *a, int n) { //formulate the size-n problem.
static int largest = 0;
if(!n) { //find the stopping condition and the corresponding return
int answer = largest;
largest = 0;
return answer;
}
else { //formulate the size-m problem.
n--; //decrement so that the proper number is added to pointer reference
if(largest <= *(a + n)) //check if element is larger
largest = *(a + n); //if larger, assign to largest
find_largest(a, n); //recursive call
}
}
The static attribute tells the compiler that you only want to initialize the variable once, and afterwards it should retain it's data. This will fix your problem because after each recursive call, largest wont be reset to zero. Instead, it will contain the value of the last call (in this case, the calling function).
At the end of the function, you should reset largest to 0 so that in the next call, it doesn't still contain the value of the call previous. This is also why a temporary variable is made - so that it can return its value before it's set to 0.
Each time you call find_largest(), you're creating a local variable int largest and assigning it the value of zero. So when n finally reaches zero, it doesn't really care what the past 5 recursive calls have done, it simply returns the zero to which you just set largest. Either make largest global, or pass it as a parameter to the function (probably better practice).
make the int largest=0; into static int largest=0; it may help.By adding static the variable largest will be initialized only once throughout your recursion.
I have this function:
int max(int arr[], int size)
{
size--;
if(size > 0)
{
int max = max(arr, size);
if(arr[max] > arr[size]) return max;
}
return size;
}
And of course it works. My question is - how does this work? Could anyone explain me this step by step? It's Saturday so maybe somebody has a bit of time :D I especially mean these two lines in if block.
You code is as follows:
1 int max(int arr[], int size){
2 size--;
3 if(size > 0){
4 int max = max(arr, size);
5 if(arr[max] > arr[size]) return max;
6 }
7 return size;
8 }
You call it by passing it array and the size (or length) of that array.
The first important point the code hits is on Line 4, when it calls itself recursively. But notice that on Line 2, the size was decreased by one. Therefore, you can think of size as being an index referring to the element of the array being considered by the current call to the function.
This means that eventually, the size of the array will be down to zero and we will be looking at the first element of the array. At this point Lines 3 through 6 are skipped, and 0 is returned.
When one of the recursive calls returns, we're left back at Line 4.
For the first return, this means that int max = 0;.
Now we are comparing the zeroth element with the first element. We return the index of whichever is greater. The next comparison will be between the second element and whichever of the first two was larger.
This continues until all the recursive calls are returned, at which point the index of the greatest element is returned to the calling function.
Note then, that return size; should be replaced with return 0 to increase clarity.
Lets step through the problem for arr[] = [1,2] which means call max(arr[], 2)
size--; // 2-1 = 1
if(size > 0) //True
{
int max = max(arr, size); //Going into the recursive call
This is the recursive run :
size--; // Now 1-1 = 0
if(size > 0) //False
return size; //0 returned
Now back into the calling function :
int max = 0 //From return
if(arr[max] > arr[size]) //arr[0]>arr[1] which is false
}
return size; //Now, control reaches here and 1 is passed back to the calling scope
}
Let's take this array for example:
int arr[] = { 42, 54, 23 };
max(arr, 3);
This function work by checking the max of the current element against the max of all previous elements. Here is a representation of the stack calls:
max(arr, 3)
max(arr, 2)
max(arr, 1)
return 0
arr[0] (arr[max] = 42) <= arr[0] (arr[size] = 42) => return size (0)
arr[0] (arr[max] = 42) <= arr[1] (arr[size] = 54) => return size (1)
arr[1] (arr[max] = 54) > arr[2] (arr[size] = 23) => return max (1)
NB: It is a bad idea to name both a variable and a function with the same identifier.
Sorry for the poor formatting of the diagram