The general approach to converting a non-tail-recursive function to a tail-recursive one is to use an extra accumulator parameter that carries the current evaluation with it through recursive calls.
In your case, this is rather straight-forward:
int count(node *start)
{
return count_helper(start, start, 0);
}
int count_helper(node *current, node *start, int acc)
{
int c;
c = 0;
if(current == NULL)
return acc;
if((current->roll_no) == 20)
c = 1;
if(current->next == start) return acc + c;
return count_helper(current->next, start, acc + c);
}
The primary changes I've made here are adding the extra accumulator parameter int acc
to your count_helper
definition, and making sure all of the return statements include acc
(when appropriate). Now the final return statement passes back the result of count_helper
directly, without modifying it; this is now tail-recursive.
It is less straight-forward when the results of recursive calls have to be combined in a way that isn't simple arithmetic.
However, as ruakh mentioned, many C compilers don't want to deal with the headache of optimizing tail-recursive calls because that simply isn't C's style. Maybe -O3
will do it?