递归方式打印三角形图案
最近我在学习递归这样的概念,并尝试用这种方法来解决一些以前用迭代方式写的旧程序,比如打印三角形图案。例如:
*
**
***
****
*****
但是我得到的输出是:
*****
****
***
**
*
None
def itriangle(x):
if x==0:
return
print("*",end="")
itriangle(x-1)
def jtriangle(y):
if y==0:
return
itriangle(y)
print()
jtriangle(y-1)
print(jtriangle(5))
这是我写的代码,首先我得到的是一个倒过来的三角形,其次最后一行返回了“None”。我该怎么解决这个问题呢?
补充:我已经修复了之前出现的“None”,那只是我写错了字母,但现在主要的问题是我得到的是一个倒三角形,我不知道该怎么解决。任何帮助都非常感谢。
5 个回答
一个递归过程有两个阶段:
- 调用阶段(向基本情况靠近),
- 返回阶段(从基本情况回来)。
在递归调用之前放的命令会在下行时执行(调用阶段),而在递归调用之后放的命令会在上行时执行(返回阶段)。
def downward(n):
if n <= 0: return
print(n * '*') # executed before recursive call
downward(n-1)
def upward(n):
if n <= 0: return
upward(n-1)
print(n * '*') # executed after recursive call
例子:
>>> downward(5)
*****
****
***
**
*
>>> upward(5)
*
**
***
****
*****
>>>
关于为什么最后会得到 None
:这是因为 print(jtriangle(5))
这行代码是在打印 jtriangle(5)
函数的返回值,而这个返回值默认是 None
,因为函数里面没有明确的 return
语句。这个函数自己已经处理了所有需要打印的内容,所以你其实不需要再打印函数的结果。你可以直接调用 jtriangle(5)
,而不需要加上 print
。
递归可能会让人感到困惑。我通常用自然语言来确保我写的递归程序是正确的。我可以这样说:
要打印一个大小为
n
的三角形,首先打印一个大小为n-1
的三角形,然后再打印一行大小为n
的线。
然后直接把它转换成代码:
def triangle(n):
if n==0:
return
triangle(n-1)
print()
line(n)
注意:像 jtriangle
和 itriangle
这样的名字并不能很好地传达意思。它们只会让你更加困惑,而递归本身就已经够复杂了,所以最好使用有意义的名字!
在开发递归程序时,我还使用了另一个强大的技巧(其实我总是这样做,但在使用递归时特别有帮助):采用自下而上的开发方式!也就是说,确保你的低层函数真的能正常工作且没有错误,在开发高层函数之前。
在我上面的例子中,确保 line
函数能正常工作,然后再为 triangle
函数写代码。如果低层函数有错误,递归会让你很麻烦,而且调试起来会更加困难。