问题
Often when solving a recursive or dynamic programming problem, I find myself drawing a recursion tree to help simplify the question for me. However, for some questions which are complicated I have access to the solution but no idea how to draw the tree.
What I have tried so far is printing out the calling function and it's parameters, and this has proved helpful in some examples. However, I saw this tree for fibonacci(5) here generated by mathematica in this answer: https://mathematica.stackexchange.com/questions/116344/how-do-i-create-a-recursive-tree-plot-for-the-fibonacci-sequence
I was wondering if I could generate the same kind of tree in a mainstream high level language like Python, Java, or C++? The tree could just have the nodes as the function name and parameters like in the image.
回答1:
Have a look at graphviz and the examples of usage.
Here is an example:
long long fib(int n)
{
if (n <= 1) return 1;
std::cout << "fib" << n << " -> fib" << n-2 << '\n';
std::cout << "fib" << n << " -> fib" << n-1 << '\n';
return fib(n-2) + fib(n-1);
}
int main()
{
std::cout << "digraph {\n";
fib(5);
std::cout << "}\n";
}
Running
program > t.dot
dot -Tpng t.dot
produced:
This is more compact than the requested image, where repeated calls with the same value are represented by one node, and N edges between nodes u,v if there are N calls from fib(u) to fib(v).
To get a tree one has to maintain unique IDs for each call. Here is an example for that:
static unsigned id = 0;
long long fib(int n)
{
auto call_id = id++;
std::cout << "fib" << call_id << " [label=\"fib(" << n << ")\"]\n";
if (n <= 1) return 1;
std::cout << "fib" << call_id << " -> fib" << id << '\n';
auto fib_n_minus_2 = fib(n-2);
std::cout << "fib" << call_id << " -> fib" << id << '\n';
auto fib_n_minus_1 = fib(n-1);
return fib_n_minus_2 + fib_n_minus_1;
}
int main()
{
std::cout << "digraph {\n";
fib(5);
std::cout << "}\n";
}
And the graph is:
回答2:
I’ve made a simple python package called recursion-visualiser which you can install via pip that helps you to easily trace function calls for any arbitary recursive function and save tree as gif and png image by simply adding a decorator to your function.
Let's draw the tree for recursive Fibonacci function. Here is the recursive code:
def fib(n):
if n <= 1:
return n
return fib(n=n - 1) + fib(n=n - 2)
def main():
# Call function
print(fib(n=6))
if __name__ == "__main__":
main()
Now let's modify the code to draw recursion tree. First let's draw a very minimalist example
# Import Visualiser class from module visualiser
from visualiser.visualiser import Visualiser as vs
# Add decorator
@vs()
def fib(n):
if n <= 1:
return n
return fib(n=n - 1) + fib(n=n-2)
def main():
print(fib(n=6))
vs.make_animation("fibonacci.gif", delay=2)
if __name__ == "__main__":
main()
The output file is saved as fibonacci.gif and fibonacci.png. Here is how output animation looks:
Also the final image of recursion tree:We can also make it better using node color and other properties:
# Import Visualiser class from module visualiser
from visualiser.visualiser import Visualiser as vs
# Add decorator
@vs(node_properties_kwargs={"shape":"record", "color":"#f57542", "style":"filled", "fillcolor":"grey"})
def fib(n):
if n <= 1:
return n
return fib(n=n - 1) + fib(n=n-2)
def main():
print(fib(n=6))
vs.make_animation("fibonacci.gif", delay=2)
if __name__ == "__main__":
main()
Here is the output which looks much better:
Here is the final image of the recursion tree:
Check out more examples at here
来源:https://stackoverflow.com/questions/55038268/program-to-generate-recursion-tree-for-generic-recursive-program