I had a homework assignment that asked for a function that uses direct recursion to find the index of the left-most, lowest, negative integer in an array. Additional requirements were for the parameters of the function to be the array and the size and that the return value for no valid value was -999.
I came up with this:
int LowIndexMinNeg(int src[], int size)
{
if (size == 0)
return -999;
int index = LowIndexMinNeg(src, size - 1);
if (index >= 0)
return (src[size - 1] < src[index]) ? (size - 1) : index;
else
return (src[size - 1] < 0) ? (size - 1) : index;
}
It works, satisfies the requirements, and got me full credit. Can this be implemented with tail recursion?
It seems to me that since you have to take the result from the recursive call to use in a comparison to decide if you pass that one on or update it that it wouldn't be possible but recursion still ties my brain in knots a it so there might be something obvious that I'm missing.
Note: My homework assignment was already turned in and graded.
Not every recursive function can be turned into a tail-recursive function. In particular, if a function makes a recursive call, but then examines the result and does different things depending on its value, then it may not be possible to make the function tail-recursive.
The tail recursion is better than non-tail recursion. As there is no task left after the recursive call, it will be easier for the compiler to optimize the code. When one function is called, its address is stored inside the stack. So if it is tail recursion, then storing addresses into stack is not needed.
A function is tail-recursive if it ends by returning the value of the recursive call. Keeping the caller's frame on stack is a waste of memory because there's nothing left to do once the recursive call returns its value. So, instead of allocating a new frame for the call, we can reuse the existing one.
In tail recursion, there is no other operation to perform after executing the recursive function itself; the function can directly return the result of the recursive call. In non-tail recursion, some operations need to be performed using the returned value of the recursive call.
If you transform the result of recursion before returning, it is not tail recursive.
EDIT: Having said that, if you want to make the function tail recursive:
const int SENTINEL= 0;
int LowIndexMinNeg(int src[], int size, int index)
{
if (size == 0)
{
if (index<0 || src[index]>=0)
return -999;
else
return index;
}
int current_index= size - 1;
int new_index= src[current_index]<=src[index] ? current_index : index;
return LowIndexMinNeg(src, size - 1, new_index);
}
And call as LowIndexMinNeg(src, src_size, src_size - 1)
EDIT2: finding the poorly termed leftmost most negative value. You can probably state that as the index of the first most negative value.
EDIT3: removing most of the conditionals, since it's easier to find the index of the lowest value, then check if it's negative.
You need to store the lowest number found so far somewhere. With your function you're using the stack to store that.
With a tail recursive function you'll need to store the lowest number found so far elsewhere. e.g:
The requirement you have for your function probably rules out all those, so you're left with something like the code you have, which cannot be written to be tail-recursive.
To get an idea of e.g. the 2 last point:
int LowIndexMinNeg(int src[], int size,int current_lowest = 0,int lowest_index = 0) {
if(size == 0)
return current_lowest == 0 ? -999 : lowest_index;
int val = src[size - 1] ;
if(val < 0 && val < current_lowest) {
current_lowest = val;
lowest_index = size -1;
}
return LowIndexMin(src,size - 1,current_lowest,lowest_index);
}
And
struct find_smallest {
int current_lowest = 0;
int lowest_index = 0
int LowIndexMinNeg(int src[], int size) {
if(size == 0)
return current_lowest == 0 ? -999 : lowest_index;
int val = src[size - 1] ;
if(val < 0 && val < current_lowest) {
current_lowest = val;
lowest_index = size - 1;
}
return LowIndexMin(src,size - 1);
}
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With