预期输出:
4 3 2 1 0 1 2 3 4
让我把它放在一个图表中:
4
3
2
1
0
1
2
3
4
让我们把它放到代码中:
def bounce(n):
print(n)
if n:
bounce(n - 1)
print(n)
或者我可以将其视为树遍历 - 向下和向上(嗯,在这种情况下,树是相当线性的):
↓
4
↓ | ↑
3
↓ | ↑
2
↓ | ↑
1
↓ | ↑
0
有多种方法可以创建tree traversal,我会在这里选择 DFS - depth-first search。
DFS 伪代码:
procedure DFS(G,v):
label v as discovered
for all edges from v to w in G.adjacentEdges(v) do
if vertex w is not labeled as discovered then
recursively call DFS(G,w)
实际上它是为图表而设计的,而不仅仅是树;对于树,我们不必执行“已发现标签”部分。
将此 DFS 转换为 Python:
def dfs(node):
for child_node in node:
dfs(child_node)
在4 3 2 1 0 的情况下,我们不需要for,因为只有一个或零个子节点 - n - 1 只要n > 0:
def our_dfs(n):
if n > 0:
child_node = n - 1
our_dfs(child_node)
但这只是遍历,还没有真正有用的东西。让我们注入我们的“业务逻辑”:
def bounce(n):
# stuff that happens before we go down
print(n)
# descend
if n > 0:
child_node = n - 1
bounce(child_node)
# stuff that happens after we are back from processing the subtree
if n > 0:
print(n)
因为我们相信良好的工艺并且我们想要生成干净的代码(好吧,我现在开始开玩笑了)我们想要只做一件事的函数 - 一个用于 DFS 的函数,一个代表我们的树的函数,一个单独的函数( s) 对于我们的业务逻辑:
def dfs(node, child_factory, before_stuff, after_stuff):
before_stuff(node)
for child_node in get_child_nodes(node):
dfs(child_node, child_factory, before_stuff, after_stuff)
after_stuff(node)
def get_child_nodes(n):
if n:
yield n - 1
def print_before(node):
print(node)
def print_after(node):
if node:
print(node)
def bounce(n):
dfs(n, get_child_nodes, print_before, print_after)
bounce(4)
也许我们可以通过使用嵌套函数使dfs 函数更简单一些:
def dfs(node, child_factory, before_stuff, after_stuff):
def f(node):
before_stuff(node)
for child_node in get_child_nodes(node):
f(child_node)
after_stuff(node)
f(node)
嘿,看一下,我还有一个想法……我们可以将其修改为一个函数,该函数返回一个可以执行 DFS 的函数 (closure):
def make_dfs(child_factory, before_stuff, after_stuff):
def dfs(node):
before_stuff(node)
for child_node in get_child_nodes(node):
dfs(child_node)
after_stuff(node)
return dfs
所以弹跳程序现在变成:
def get_child_nodes(n):
if n:
yield n - 1
def print_before(node):
print(node)
def print_after(node):
if node:
print(node)
def make_dfs(child_factory, before_stuff, after_stuff):
def dfs(node):
before_stuff(node)
for child_node in get_child_nodes(node):
dfs(child_node)
after_stuff(node)
return dfs
bounce = make_dfs(get_child_nodes, print_before, print_after)
bounce(4)
那么,这个解决方案有什么了不起的呢? (注意:仍然在开玩笑,部分)你知道,Python 有一个recursion limit。可以嵌套多少个函数调用是有限的,而且这个数字非常低。这是使用递归函数处理未知输入的一大缺点(有时甚至是安全问题)。所以现在怎么办?好吧,只需将 make_dfs 的实现替换为基于堆栈的东西(参见 DFS 维基百科页面)而不是递归。完毕。您无需触摸其他任何东西。