Hello guys I have a question about how two recursions actually work in this particular piece of code
void inOrder(struct node* r)
{
if(r!=NULL){
inOrder(r->left); // a
printf("%d ", r->value); // b
inOrder(r->right); // c
}
}
so In which order the a , c function will be execute
thank you
You are probably referring to the call tree of recursion, here a little gif that will explain it visually :
way better that I could with words.
I made the gif but the work is NOT mine, I took the prints from this presentation www.cc.gatech.edu/~bleahy/cs1311/cs1311lecture12wdl.ppt
The same as if they weren't recursive calls: (a) goes first, then the printf, then (c).
Related
I understand that for C at least the stack frame and return address are written to the stack every time the recursive function is called, but is there an obscure way of making it not run out of memory? Obviously this is purely a hypothetical question as I can't imagine a use case for it.
You can emulate recursion using a stack
The part of memory related to function calls and static variables (declared with int x; in C) is separate from the part of memory related to dynamic allocation (using malloc() in C). Only the former, called "the stack" is limited and will lead to a "Stack Overflow" error. Well, of course that's not entirely true. The latter is called "the heap" and of course your computer is not magic and will run out of memory at some point if you really try to push its limits.
Recursive function to loop and stack
How can you emulate recursion with loop and stack?
How ti rewrite a recursive method by using a stack?
Way to go from recursion to iteration
You can use tail-recursion to avoid adding layers to the call stack
Stack overflow is due to the size of the call stack. Imagine a function like this:
int f(int n)
{
int x;
if (n < 2)
{
return 1;
}
else
{
x = f(n-1);
return n * x;
}
}
When making the recursive call to f, the computer needs to keep some note of the fact that we'll need to do one more multiplication once the recursive call is completed. Taking note of this is achieved by adding a layer to a "call stack" with some information on the values of variables, and where in the code we are. This requires memory and will lead to stack overflow in case the stack becomes too big.
Now compare with the following code:
int f(int n, int acc)
{
if (n < 2)
{
return acc;
}
else
{
return f(n-1, n * acc);
}
}
This time the recursive call is directly encapsulated in the return, meaning there is no more work to do after the recursive call. Imagine you asked me to do a job and report the result to you; by making the recursive call I'm delegating some work to my friend; then instead of staying around waiting for my friend to report back to me so that I can report back to you, I leave immediately and tell my friend to report directly to you. This saves memory by "cutting the middle man".
Read more:
Wikipedia: Tail call
Wikipedia: Tail-recursive functions
In languages that feature lazy evaluation, you can write a seemingly infinitely-recursive function, then only evaluate it as far as required:
Haskell infinite recursion
I have two simple functions:
a)
drawRight(x){ // where x is integer
if(x == 0 )
draw();
else{
drawRight(x-1);
doSomething();
drawLeft(x-1);
}
}
b) (very similar to a) )
drawLeft(x){ // where x is integer
if(x == 0 )
draw();
else{
drawRight(x-1);
doSomething2();
drawLeft(x-1);
}
}
My question is: is it even possible to draw flowchart if i call e.g drawRight(5) ? I did flowchart for only self calling recurvive function but cant find solution for this one.
Any help would be appreciated.
A recursive function is usually called and processed using a stack in any programming language I know of. The flowchart might not exactly follow the rules a programming language follow to run a code with recursive functions, but it shows how a flowchart can run a recursive snippet:
Note that functions are added to the stack in the reversed order. For example, if drawRight calls drawRight, doSomething, and drawLeft, they will be added to stack as drawLeft, doSomething, and drawRight. This way drawRight will be called first, then doSomething, and drawLeft last. The executions would happen as expected.
The flowchart would have less wires if case is used instead of conditional element.
I believe the flowchart would look like this. I did it for drawRight(2), as it gets pretty massive very quickly
The actual order of terminal calls would then be
draw
doSomething
draw
doSomething
draw
doSomething2
draw
I have a Board (a.k.a. &mut Vec<Vec<Cell>>) which I would like to update while iterating over it. The new value I want to update with is derived from a function which requires a &Vec<Vec<Cell>> to the collection I'm updating.
I have tried several things:
Use board.iter_mut().enumerate() and row.iter_mut().enumerate() so that I could update the cell in the innermost loop. Rust does not allow calling the next_gen function because it requires a &Vec<Vec<Cell>> and you cannot have a immutable reference when you already have a mutable reference.
Change the next_gen function signature to accept a &mut Vec<Vec<Cell>>. Rust does not allow multiple mutable references to an object.
I'm currently deferring all the updates to a HashMap and then applying them after I've performed my iteration:
fn step(board: &mut Board) {
let mut cells_to_update: HashMap<(usize, usize), Cell> = HashMap::new();
for (row_index, row) in board.iter().enumerate() {
for (column_index, cell) in row.iter().enumerate() {
let cell_next = next_gen((row_index, column_index), &board);
if *cell != cell_next {
cells_to_update.insert((row_index, column_index), cell_next);
}
}
}
println!("To Update: {:?}", cells_to_update);
for ((row_index, column_index), cell) in cells_to_update {
board[row_index][column_index] = cell;
}
}
Full source
Is there a way that I could make this code update the board "in place", that is, inside the innermost loop while still being able to call next_gen inside the innermost loop?
Disclaimer:
I'm learning Rust and I know this is not the best way to do this. I'm playing around to see what I can and cannot do. I'm also trying to limit any copying to restrict myself a little bit. As oli_obk - ker mentions, this implementation for Conway's Game of Life is flawed.
This code was intended to gauge a couple of things:
if this is even possible
if it is idiomatic Rust
From what I have gathered in the comments, it is possible with std::cell::Cell. However, using std:cell:Cell circumvents some of the core Rust principles, which I described as my "dilemma" in the original question.
Is there a way that I could make this code update the board "in place"?
There exists a type specially made for situations such as these. It's coincidentally called std::cell::Cell. You're allowed to mutate the contents of a Cell even when it has been immutably borrowed multiple times. Cell is limited to types that implement Copy (for others you have to use RefCell, and if multiple threads are involved then you must use an Arc in combination with somethinng like a Mutex).
use std::cell::Cell;
fn main() {
let board = vec![Cell::new(0), Cell::new(1), Cell::new(2)];
for a in board.iter() {
for b in board.iter() {
a.set(a.get() + b.get());
}
}
println!("{:?}", board);
}
It entirely depends on your next_gen function. Assuming we know nothing about the function except its signature, the easiest way is to use indices:
fn step(board: &mut Board) {
for row_index in 0..board.len() {
for column_index in 0..board[row_index].len() {
let cell_next = next_gen((row_index, column_index), &board);
if board[row_index][column_index] != cell_next {
board[row_index][column_index] = cell_next;
}
}
}
}
With more information about next_gen a different solution might be possible, but it sounds a lot like a cellular automaton to me, and to the best of my knowledge this cannot be done in an iterator-way in Rust without changing the type of Board.
You might fear that the indexing solution will be less efficient than an iterator solution, but you should trust LLVM on this. In case your next_gen function is in another crate, you should mark it #[inline] so LLVM can optimize it too (not necessary if everything is in one crate).
Not an answer to your question, but to your problem:
Since you are implementing Conway's Game of Life, you cannot do the modification in-place. Imagine the following pattern:
00000
00100
00100
00100
00000
If you update line 2, it will change the 1 in that line to a 0 since it has only two 1s in its neighborhood. This will cause the middle 1 to see only two 1s instead of the three that were there to begin with. Therefor you always need to either make a copy of the entire Board, or, as you did in your code, write all the changes to some other location, and splice them in after going through the entire board.
To better understand recursion, I'm trying to count how many characters are between each pair of (),
not counting characters that are within other ()s. For example:
(abc(ab(abc)cd)(()ab))
would output:
Level 3: 3
Level 2: 4
Level 3: 0
Level 2: 2
Level 1: 3
Where "Level" refers to the level of () nesting. So level three would mean that the characters are within a pair(1) within a pair(2) within a pair(3).
To do this, my guess is that the easiest thing to do is to implement some sort of recursive call to the function, as commented inside the function "recursiveParaCheck". What is my approach as I begin thinking about a recurrence relationship?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int recursiveParaCheck(char input[], int startPos, int level);
void main()
{
char input[] = "";
char notDone = 'Y';
do
{
//Read in input
printf("Please enter input: ");
scanf(" %s", input);
//Call Recursive Function to print out desired information
recursiveParaCheck(input, 1, 1);
printf("\n Would you like to try again? Y/N: ");
scanf(" %c", ¬Done);
notDone = toupper(notDone);
}while(notDone == 'Y');
}
int recursiveParaCheck(char input[], int startPos, int level)
{
int pos = startPos;
int total = 0;
do
{
if(input[pos] != '(' && input[pos] != ')')
{
++total;
}
//What is the base case?
if(BASE CASE)
{
//Do something?
}
//When do I need to make a recursive call?
if(SITUATION WHERE I MAKE RECURSIVE CALL)
{
//Do something?
}
++pos;
}while(pos < 1000000); // assuming my input will not be this long
}
Recursion is a wonderful programming tool. It provides a simple, powerful way of approaching a variety of problems. It is often hard, however, to see how a problem can be approached recursively; it can be hard to "think" recursively. It is also easy to write a recursive program that either takes too long to run or doesn't properly terminate at all. In this article we'll go over the basics of recursion and hopefully help you develop, or refine, a very important programming skill.
What is Recursion?
In order to say exactly what recursion is, we first have to answer "What is recursion?" Basically, a function is said to be recursive if it calls itself.
You may be thinking this is not terribly exciting, but this function demonstrates some key considerations in designing a recursive algorithm:
It handles a simple "base case" without using recursion.
In this example, the base case is "HelloWorld(0)"; if the function is asked to print zero times then it returns without spawning any more "HelloWorld"s.
It avoids cycles.
Why use Recursion?
The problem we illustrated above is simple, and the solution we wrote works, but we probably would have been better off just using a loop instead of bothering with recursion. Where recursion tends to shine is in situations where the problem is a little more complex. Recursion can be applied to pretty much any problem, but there are certain scenarios for which you'll find it's particularly helpful. In the remainder of this article we'll discuss a few of these scenarios and, along the way, we'll discuss a few more core ideas to keep in mind when using recursion.
Scenario #1: Hierarchies, Networks, or Graphs
In algorithm discussion, when we talk about a graph we're generally not talking about a chart showing the relationship between variables (like your TopCoder ratings graph, which shows the relationship between time and your rating). Rather, we're usually talking about a network of things, people, or concepts that are connected to each other in various ways. For example, a road map could be thought of as a graph that shows cities and how they're connected by roads. Graphs can be large, complex, and awkward to deal with programatically. They're also very common in algorithm theory and algorithm competitions. Luckily, working with graphs can be made much simpler using recursion. One common type of a graph is a hierarchy, an example of which is a business's organization chart:
Name Manager
Betty Sam
Bob Sally
Dilbert Nathan
Joseph Sally
Nathan Veronica
Sally Veronica
Sam Joseph
Susan Bob
Veronica
In this graph, the objects are people, and the connections in the graph show who reports to whom in the company. An upward line on our graph says that the person lower on the graph reports to the person above them. To the right we see how this structure could be represented in a database. For each employee we record their name and the name of their manager (and from this information we could rebuild the whole hierarchy if required - do you see how?).
Now suppose we are given the task of writing a function that looks like "countEmployeesUnder(employeeName)". This function is intended to tell us how many employees report (directly or indirectly) to the person named by employeeName. For example, suppose we're calling "countEmployeesUnder('Sally')" to find out how many employees report to Sally.
To start off, it's simple enough to count how many people work directly under her. To do this, we loop through each database record, and for each employee whose manager is Sally we increment a counter variable. Implementing this approach, our function would return a count of 2: Bob and Joseph. This is a start, but we also want to count people like Susan or Betty who are lower in the hierarchy but report to Sally indirectly. This is awkward because when looking at the individual record for Susan, for example, it's not immediately clear how Sally is involved.
A good solution, as you might have guessed, is to use recursion. For example, when we encounter Bob's record in the database we don't just increment the counter by one. Instead, we increment by one (to count Bob) and then increment it by the number of people who report to Bob. How do we find out how many people report to Bob? We use a recursive call to the function we're writing: "countEmployeesUnder('Bob')". Here's pseudocode for this approach:
function countEmployeesUnder(employeeName)
{
declare variable counter
counter = 0
for each person in employeeDatabase
{
if(person.manager == employeeName)
{
counter = counter + 1
counter = counter + countEmployeesUnder(person.name)
}
}
return counter
}
If that's not terribly clear, your best bet is to try following it through line-by-line a few times mentally. Remember that each time you make a recursive call, you get a new copy of all your local variables. This means that there will be a separate copy of counter for each call. If that wasn't the case, we'd really mess things up when we set counter to zero at the beginning of the function. As an exercise, consider how we could change the function to increment a global variable instead. Hint: if we were incrementing a global variable, our function wouldn't need to return a value.
Mission Statements
A very important thing to consider when writing a recursive algorithm is to have a clear idea of our function's "mission statement." For example, in this case I've assumed that a person shouldn't be counted as reporting to him or herself. This means "countEmployeesUnder('Betty')" will return zero. Our function's mission statment might thus be "Return the count of people who report, directly or indirectly, to the person named in employeeName - not including the person named employeeName."
Let's think through what would have to change in order to make it so a person did count as reporting to him or herself. First off, we'd need to make it so that if there are no people who report to someone we return one instead of zero. This is simple -- we just change the line "counter = 0" to "counter = 1" at the beginning of the function. This makes sense, as our function has to return a value 1 higher than it did before. A call to "countEmployeesUnder('Betty')" will now return 1.
However, we have to be very careful here. We've changed our function's mission statement, and when working with recursion that means taking a close look at how we're using the call recursively. For example, "countEmployeesUnder('Sam')" would now give an incorrect answer of 3. To see why, follow through the code: First, we'll count Sam as 1 by setting counter to 1. Then when we encounter Betty we'll count her as 1. Then we'll count the employees who report to Betty -- and that will return 1 now as well.
It's clear we're double counting Betty; our function's "mission statement" no longer matches how we're using it. We need to get rid of the line "counter = counter + 1", recognizing that the recursive call will now count Betty as "someone who reports to Betty" (and thus we don't need to count her before the recursive call).
As our functions get more and more complex, problems with ambiguous "mission statements" become more and more apparent. In order to make recursion work, we must have a very clear specification of what each function call is doing or else we can end up with some very difficult to debug errors. Even if time is tight it's often worth starting out by writing a comment detailing exactly what the function is supposed to do. Having a clear "mission statement" means that we can be confident our recursive calls will behave as we expect and the whole picture will come together correctly.
I've been writing (unsophisticated) code for a decent while, and I feel like I have a somewhat firm grasp on while and for loops and if/else statements. I should also say that I feel like I understand (at my level, at least) the concept of recursion. That is, I understand how a method keeps calling itself until the parameters of an iteration match a base case in the method, at which point the methods begin to terminate and pass control (along with values) to previous instances and eventually an overall value of the first call is determined. I may not have explained it very well, but I think I understand it, and I can follow/make traces of the structured examples I've seen. But my question is on creating recursive methods in the wild, ie, in unstructured circumstances.
Our professor wants us to write recursively at every opportunity, and has made the (technically inaccurate?) statement that all loops can be replaced with recursion. But, since many times recursive operations are contained within while or for loops, this means, to state the obvious, not every loop can be replaced with recursion. So...
For unstructured/non-classroom situations,
1) how can I recognize that a loop situation can/cannot be turned into a recursion, and
2) what is the overall idea/strategy to use when applying recursion to a situation? I mean, how should I approach the problem? What aspects of the problem will be used as recursive criteria, etc?
Thanks!
Edit 6/29:
While I appreciate the 2 answers, I think maybe the preamble to my question was too long because it seems to be getting all of the attention. What I'm really asking is for someone to share with me, a person who "thinks" in loops, an approach for implementing recursive solutions. (For purposes of the question, please assume I have a sufficient understanding of the solution, but just need to create recursive code.) In other words, to apply a recursive solution, what am I looking for in the problem/solution that I will then use for the recursion? Maybe some very general statements about applying recursion would be helpful too. (note: please, not definitions of recursion, since I think I pretty much understand the definition. It's just the process of applying them I am asking about.) Thanks!
Every loop CAN be turned into recursion fairly easily. (It's also true that every recursion can be turned into loops, but not always easily.)
But, I realize that saying "fairly easily" isn't actually very helpful if you don't see how, so here's the idea:
For this explanation, I'm going to assume a plain vanilla while loop--no nested loops or for loops, no breaking out of the middle of the loop, no returning from the middle of the loop, etc. Those other things can also be handled but would muddy up the explanation.
The plain vanilla while loop might look like this:
1. x = initial value;
2. while (some condition on x) {
3. do something with x;
4. x = next value;
5. }
6. final action;
Then the recursive version would be
A. def Recursive(x) {
B. if (some condition on x) {
C. do something with x;
D. Recursive(next value);
E. }
F. else { # base case = where the recursion stops
G. final action;
H. }
I.
J. Recursive(initial value);
So,
the initial value of x in line 1 became the orginial argument to Recursive on line J
the condition of the loop on line 2 became the condition of the if on line B
the first action inside the loop on line 3 became the first action inside the if on line C
the next value of x on line 4 became the next argument to Recursive on line D
the final action on line 6 became the action in the base case on line G
If more than one variable was being updated in the loop, then you would often have a corresponding number of arguments in the recursive function.
Again, this basic recipe can be modified to handle fancier situations than plain vanilla while loops.
Minor comment: In the recursive function, it would be more common to put the base case on the "then" side of the if instead of the "else" side. In that case, you would flip the condition of the if to its opposite. That is, the condition in the while loop tests when to keep going, whereas the condition in the recursive function tests when to stop.
I may not have explained it very well, but I think I understand it, and I can follow/make traces of the structured examples I've seen
That's cool, if I understood your explanation well, then how you think recursion works is correct at first glance.
Our professor wants us to write recursively at every opportunity, and has made the (technically inaccurate?) statement that all loops can be replaced with recursion
That's not inaccurate. That's the truth. And the inverse is also possible: every time a recursive function is used, that can be rewritten using iteration. It may be hard and unintuitive (like traversing a tree), but it's possible.
how can I recognize that a loop can/cannot be turned into a recursion
Simple:
what is the overall idea/strategy to use when doing the conversion?
There's no such thing, unfortunately. And by that I mean that there's no universal or general "work-it-all-out" method, you have to think specifically for considering each case when solving a particular problem. One thing may be helpful, however. When converting from an iterative algorithm to a recursive one, think about patterns. How long and where exactly is the part that keeps repeating itself with a small difference only?
Also, if you ever want to convert a recursive algorithm to an iterative one, think about that the overwhelmingly popular approach for implementing recursion at hardware level is by using a (call) stack. Except when solving trivially convertible algorithms, such as the beloved factorial or Fibonacci functions, you can always think about how it might look in assembler, and create an explicit stack. Dirty, but works.
for(int i = 0; i < 50; i++)
{
for(int j = 0; j < 60; j++)
{
}
}
Is equal to:
rec1(int i)
{
if(i < 50)
return;
rec2(0);
rec1(i+1);
}
rec2(int j)
{
if(j < 60)
return;
rec2(j + 1);
}
Every loop can be recursive. Trust your professor, he is right!