As I know, a recursive function is a function which calls it self, and it has the characteristic of having a base case. This is a function for pre-order traversal of a binary tree. Is this a recursive function? Absence of the base case confuses me.
void pre_order(struct node* current){ // preorder traversal
printf("%d\n",current->data);
if(current->left != NULL){
pre_order(current->left);
}
if(current->right !=NULL){
pre_order(current->right);
}
}
Since it calls itself it is a recursive function. That's how simple it is. There's also a base case here, but it's a little hidden perhaps. When we get to a leaf in this binary tree both left and right childs will be equal to null and therefore no more recursive calls will happen. That's our base case that's a little hidden.
Related
I was working on this easy problem to practice basic Kotlin, and I ran into a stack overflow with the following code on the recursive return line:
class Solution {
fun isPalindrome(s: String): Boolean {
val cleaned = s.toLowerCase().replace(Regex("[^a-z0-9]"), "")
tailrec fun isPalindrome(start: Int, end: Int): Boolean {
if (start >= end) return true
return cleaned[start] == cleaned[end] && isPalindrome(start+1, end-1)
}
return isPalindrome(0, cleaned.length-1)
}
}
My understanding of tailrec is that it's supposed to convert my recursive function into an iterative one, which wouldn't be susceptible to this sort of crash. If I didn't implement tail recursion correctly, the compiler is supposed to issue an error.
Can someone explain to me why this crashes on large inputs, just like a standard recursive call would?
This behavior looks like a missing optimization of tail calls in short circuiting operators, where the fact that the last operand is being evaluated means that the expression result doesn't depend anymore on the previous operands.
Meanwhile you can rewrite your return statement as
return if (cleaned[start] != cleaned[end]) false else isPalindrome(start+1, end-1)
to get the same result + tail call optimization.
For me when making a recursive method. I always need to spend a lot of time to do it, because I will make some test cases and to see whether my recursive case works and to draw a stack diagram. However, when I ask other about it, they just say that I need to believe myself it will work. How am I suppose to believe that if you don't know what is going on in the recursive case?
You define what is going on in the recursive case, just as you define the rest of the method. Imagine someone else wrote a method to do what the one you are writing does; you wouldn't have a problem calling that, would you? The only difference is that you are that method's author, and it just happens to be the one being written.
For example: I am writing the following method:
// Sort array a[i..j-1] in ascending order
method sort_array( a, i, j ) {
..
}
The base case is easy:
if ( i >= j-1 ) // there is at most one element to be sorted
return; // a[i..j-1] is already sorted
Now, when that isn't true, I could do the following:
else {
k = index_of_max( a, i, j );
swap( a, j-1, k );
At this point, I know that a[j-1] has the correct value, so I just need to sort what comes before it -- fortunately, I have a method to do just that:
sort_array( a, i, j-1 );
}
No leap of faith is required; I know that recursive call will work because I wrote the method to do just that.
I have a problem that I'm trying to solve, I want to implement a method that takes a clique and returns the largest clique that contains that clique. The method I'm working on is recursive and uses backtracking to accept or refuse solutions according to the clique definition. My problem is I don't want to use Bron-Kerbosch algorithm as I want only one parameter to be passed to the method.
Here's a pesudo code for what I did:
public ArrayList<Integer> findClique(ArrayList<Integer> R)
{
if(no more candidates)
{
return R;
}
else
{
for(int candidate = next candidate; candidate <nodesNmuber; node++)
if(connected(R,candidate))
{
R.add(candidate);
findClique(R);
}
printOutput(R);
R.remove(candidate);
}
}
Can you help me with ideas on how to choose the condition that breaks the recursion? I don't know how to keep the value of next candidate until the next loop without passing it in the method parameter !
Let's say I have a JavaScript function
function f(x) {
return a(b(x), c(x));
}
How would I convert that into a point free function? through composing functions? Also are there resources for more info on this?
In general, there's no easy rule to follow when you turn functions into point free style. Either you are going to have to guess, or you can just automate it. In the Haskell IRC channel, we have the lambdabot which is great at turning Haskell functions into point-free style. I usually just consult that, and then work my way backwards if I need to know how it works.
Your particular example can be solved using a couple of helpful functions. I'll show you below how it works, but be aware that it might require a lot of playing around to understand. It also helps if you know really, really basic lambda calculus, because the JavaScript syntax tends to get in the way sometimes.
Anyway, here goes:
Basically, to do this properly, you need three functions: fmap(f, g), ap(f, g) and curry(f). When you have those, f(x) is easily defined as (and this looks much neater in e.g. Haskell)
f = ap(fmap(curry(a), b), c);
The interesting bit lies in defining those three functions.
curry
Normally when you define functions of multiple arguments in JavaScript, you define them like
function f(x, y) {
// body
}
and you call them by doing something like f(3, 4). This is what is called an "uncurried function" in functional programming. You could also imagine defining functions like
function f(x) {
return function(y) {
//body
}
}
These functions are called "curried functions." (By the way, they are named after a mathematician whose name was Curry, if you wonder about the strange name.) Curried functions are instead called by doing
f(3)(4)
but other than that, the two functions behave very similarly. One difference is that it is easier to work with a point-free style when the functions are curried. Our curry function simply takes an uncurried function like the first one and turns it into a curried function like the second one. curry can be defined as
function curry(f) {
return function(a) {
return function(b) {
return f(a, b);
}
}
}
Now, you can use this. Instead of doing pow(3, 4) to get 81, you can do
cpow = curry(pow);
cpow(3)(4);
cpow is the curried version of pow. It doesn't take both arguments at the same time -- it takes them separately. In your specific case, this allows us to go from
function f(x) {
return a(b(x), c(x));
}
to
function f(x) {
return curry(a)(b(x))(c(x));
}
This is progress! (Although I admit it looks very weird in JavaScript...) Now, on to less spicy pastures.
fmap
The second piece of the puzzle is fmap(f, g), which takes two functions as arguments and composes them. What I'm saying is,
fmap(f, g)(x) == f(g(x))
This is easy to define, we just let
function fmap(f, g) {
return function(x) {
return f(g(x));
}
}
This is useful when you want to do two things in sequence. Say you want to do the useless operation log(exp(x)). You could do this the traditional way:
function logexp(x) {
return log(exp(x));
}
You could instead just do
logexp = fmap(log, exp);
This is commonly called composing two functions. To connect this to your example, last we left it off, we had refactored it into
function f(x) {
return curry(a)(b(x))(c(x));
}
We now notice some visual similarity between this and the function body of fmap. Let's rewrite this with fmap and it becomes
function f(x) {
return fmap(curry(a), b)(x)(c(x));
}
(to see how I got there, imagine that f = curry(a) and g = b. The last bit with c(x) isn't changed.)
ap
Our last puzzle piece is ap(f, g), which takes two functions and an argument, and does a weird thing. I won't even try to explain it, so I'll just show you what it does:
ap(f, g)(x) == f(x)(g(x))
Remember that f is really just a function of two arguments, only we write it a little differently to be able to do magic. ap is defined in JavaScript as
function ap(f, g) {
return function(x) {
return f(x)(g(x));
}
}
So, to put this in a more practical context: Say you want to raise a number to the square root of itself. You could do
function powsqrt(x) {
return pow(x, sqrt(x));
}
or, with your newfound knowledge of ap and remembering cpow from the first part about currying, you could also do
powsqrt = ap(cpow, sqrt);
This works because cpow is the curried version of pow. You can verify for yourself that this becomes the right thing when the definition of ap is expanded.
Now, to tie all this together with your example, we need to turn
function f(x) {
return fmap(curry(a), b)(x)(c(x));
}
Into the final, completely point-free version. If we look at the definition of ap, we see we can do something here to turn this into the point-free version!
function f(x) {
return ap(fmap(curry(a), b), c)(x);
}
Basically, the easiest way to understand this is to now "unfold" the call to ap. Replace the call to ap with the function body! What we get then, by merely substituting, is
function f(x) {
return function(y) {
return fmap(curry(a), b)(y)(c(y));
}(x);
}
I've renamed one x to y to avoid name collisions. This is still a bit weird, but we can make it a little shorter. After all, it is the same thing as
function f(x) {
return fmap(curry(a), b)(x)(c(x));
}
which was what we started with! Our call to ap was correct. If you want to, you can further unfold this to see that after everything is said and done, we actually end up with the very thing we started with. I leave that as an exercise.
Wrapping Up
Anyway, the last refactoring of your code made it into
function f(x) {
return ap(fmap(curry(a), b), c)(x);
}
which of course is the same thing as
f = ap(fmap(curry(a), b), c);
And that's it!
A theoretical question here about the base or halting case in a recursive method, what's its standards?
I mean, is it normal not to have body in it, just a return statement?
Is it always like the following:
if (input operation value)
return sth;
Do you have different thoughts about it?
The pattern for recursive functions is that they look something like this:
f( value )
if ( test value )
return value
else
return f( simplify value )
I don't think you can say much more than that about general cases.
The base case is to terminate the loop (avoid becoming an infinite recursion). There's no standard in the base case, any input that is simple enough to be solved exactly can be chosen as one.
For example, this is perfectly valid:
int factorial (int n) {
if (n <= 5) {
// Not just a return statement
int x = 1;
while (n > 0) {
x *= n;
-- n;
}
return x;
} else {
return n * factorial(n-1);
}
}
In some cases, your base case is
return literal
In some cases, your base case is not simply "return a literal".
There cannot be a "standard" -- it depends on your function.
The "Syracuse Function" http://en.wikipedia.org/wiki/Collatz_conjecture for example,
doesn't have a trivial base case or a trivial literal value.
"Do you have different thoughts about it??" Isn't really a sensible question.
The recursion has to terminate, that's all. A trivial tail recursion may have a "base case" that returns a literal, or it may be a calculation. A more complex recursion may not have a trivial "base case".
It depends entirely on the particular recursive function. In general, it can't be an empty return; statement, though - for any recursive function that returns a value, the base case should also return a value of that type, since func(base) is also a perfectly valid call. For example, a recursive factorial function would return a 1 as the base value.