![]() | Physics and Astronomy |
Back to top
RecursionTo iterate is human, to recurse divine.Computer Science saying
God is subtle but he is not malicious.
Functions that call themselvesRecursion is an extremely simple concept: a function simply calls itself. Of course, a function can't always call itself, that would create an infinite loop, so all recursive functions have some sort of test before they call themselves.void myfun(some_args) { /* Do some stuff */ if ( some_test) myfun(some_other_args); } A variation on the above is to do the test inside the function: void myfun(some_args) { if (I_didnt_need_to_be_called) return; /* Do some stuff */ myfun(some_other_args); }or you may need a combination of the two. Example: geneologySuppose a structure for a person consists of their name and date of birth, and a list of their children. You could print out the name of a person and all their descendents with the following pseudo-code:To print a person and their descendents
When recursion goes wrongThe biggest problem is the internal test or tests: either the recursion never stops or some possibilities get missed out. Consider the following rather over-the-top way of calculating a factorial:int factorial(int i) { if ( 1 > 0 ) // Bug! return i * factorial(i - 1); return 1; }You can see what it's meant to do but we've written '1' instead of 'i' so it will go on for ever. The first stage of debugging is just to print out its arguments: int factorial(int i) { fprintf(stderr, "i: %d\n", i); if ( 1 > 0 ) // Bug! return i * factorial(i - 1); return 1; }You can get even more details by adding an extra debugging argument to tell you the depth: int factorial(int i, int depth) { int d; for(d = 0; d <= depth; ++d) fprintf(stderr, " "); fprintf(stderr, "i: %d (depth %d)\n", i, depth); if ( depth > 12) { fprintf(stderr, "Too deep!\n"); exit(-1); } if ( 1 > 0 ) // Bug! return i * factorial(i - 1); return 1; }Here we have done two things:
Be prepared to add some debugging output to your recursive routine. Using a wrapperIt may be very inconvenient to add an extra argument to your routine because it is called elsewhere, there are header files, etc. In that case just create a simple wrapper:int factorial(int i) { return factorial_debug(i, 0); } |