代码说明:输入n是整数,其他输入是list(降序(。 例如,n=3
、A=list(range(n,0,-1))
、B=[]
、C=[]
(较大的整数表示较大的圆盘(。
输入列表变量(start_
、inter_
、end_
(名称必须A
、B
、C
因为河内函数包括全局变量A
、B
、C
。这是一件烦人的事情。
如何在没有全局变量的情况下用列表表示每个步骤?换句话说,基本情况的操作(追加、删除(如何取决于输入位置而不是变量名称。
例如:
start_
是第二个输入变量,end_
是第四个输入变量。
基本情况操作 -> 第四个输入变量.append(第二个输入变量[-1], 第二个输入变量。删除(第二个输入变量[-1](
def Hanoi(n,start_,inter_,end_):
if n==1:
end_.append(start_[-1])
start_.remove(start_[-1])
print('start_peg , inter_peg, end_peg :{}t{}t{}'.format(A,B,C))
else:
Hanoi(n-1,start_,end_,inter_)
Hanoi(1,start_,inter_,end_)
Hanoi(n-1,inter_,start_,end_)
n=3
A=list(range(n,0,-1))
B,C=[],[]
Hanoi(n,A,B,C) #variable name of three list input must be A,B,C
Out:
start_peg , inter_peg, end_peg :[3, 2] [] [1]
start_peg , inter_peg, end_peg :[3] [2] [1]
start_peg , inter_peg, end_peg :[3] [2, 1] []
start_peg , inter_peg, end_peg :[] [2, 1] [3]
start_peg , inter_peg, end_peg :[1] [2] [3]
start_peg , inter_peg, end_peg :[1] [] [3, 2]
start_peg , inter_peg, end_peg :[] [] [3, 2, 1]
第五行----中---- (start_,inter_,end_(而不是(A,B,C(
def Hanoi(n,start_,inter_,end_):
if n==1:
end_.append(start_[-1])
start_.remove(start_[-1])
print('start_peg , inter_peg, end_peg :{}t{}t{}'.format(start_,inter_,end_))
else:
Hanoi(n-1,start_,end_,inter_)
Hanoi(1,start_,inter_,end_)
Hanoi(n-1,inter_,start_,end_)
# it's possible to use any input variable name
n=3
a=list(range(n,0,-1))
b,c=[],[]
Hanoi(n,a,b,c)
Out:
start_peg , inter_peg, end_peg :[3, 2] [] [1]
start_peg , inter_peg, end_peg :[3] [1] [2]
start_peg , inter_peg, end_peg :[] [3] [2, 1]
start_peg , inter_peg, end_peg :[] [2, 1] [3]
start_peg , inter_peg, end_peg :[2] [3] [1]
start_peg , inter_peg, end_peg :[] [1] [3, 2]
start_peg , inter_peg, end_peg :[] [] [3, 2, 1]
可以使用列表列表和可选参数来保留三个列表的顺序。这样,您始终可以以相同的方式打印它们,同时根据算法需要操作项目:
def Hanoi(n,start_,inter_,end_, pegs=None): # new optional argument
if pegs is None:
pegs = [start_, inter_, end_] # build a list of lists if one was not passed in
if n==1:
end_.append(start_.pop()) # using pop makes this much easier
print('start_peg , inter_peg, end_peg :{}t{}t{}'.format(*pegs)) # prints in order
else:
Hanoi(n-1,start_,end_,inter_, pegs) # pass on the list of lists in each recursive call
Hanoi(1,start_,inter_,end_, pegs) # this lets the original order be preserved
Hanoi(n-1,inter_,start_,end_, pegs)
n=3
A=list(range(n,0,-1))
B,C=[],[]
Hanoi(n, A, B, C)
我对你的代码做了一个偶然的更改,以调用list.pop
而不是索引,然后调用remove
来摆脱最后一项。这更有效(O(1)
而不是O(N)
(,也更简单!
更重要的更改是使用列表pegs
列表来保留进行原始调用时三个列表的顺序。print
可以使用它来以一致的顺序将它们全部写出来。
如何在没有全局变量的情况下用列表表示每个步骤?
答案很简单。只需使用您传入的变量的名称:
print('start_peg , inter_peg, end_peg :{}t{}t{}'.format(start_, inter_, end_))
这就是python处理对象的方式。对象绑定到给定作用域中的名称,但 if 可以在多个作用域中命名。您可以将对象绑定到任意数量的名称。
例如,假设您有(在函数外部(
n = 3
A = list(range(n, 0, -1))
B = []
C = []
赋值将四个不同的对象(一个int
和三个list
(绑定到全局命名空间中的四个不同名称(n
、A
、B
、C
(。现在当你打电话
Hanoi(n, A, B, C)
这四个对象绑定到函数命名空间中的名称n
、start_
、inter_
、end_
。无论使用全局名称A
还是本地名称start_
,您都在引用内存中的同一对象。
在不相关的注释中,start_.remove(start_[-1])
对已知道其索引的对象执行不必要的按值搜索。由于您已经将值分配给上面行上的正确堆栈,因此执行删除的更简单方法是
del start_[-1]
一个更优雅的解决方案可能是将这两行都替换为
end_.append(start.pop())
您可以使用第一个元素"命名"列表:
n=3, A=["A"]+list(range(n,0,-1)), B=["B"], C=["C"]
并修改打印语句:
print('start_peg , inter_peg, end_peg :{}t{}t{}'.format( *sorted((start_, inter_, end_)) ))
排序将在"A","B","C"上生效。
编辑:如果你不喜欢上面的解决方案,你可以创建一个新类:
class Hanoi:
def __init__(self,start_):
self.n= len(start_)
self.A,self.B,self.C= start_,[],[]
def go(self):
self.Hanoi(self.n,self.A,self.B,self.C)
def Hanoi(self,n,start_,inter_,end_): # <--- your code
if n==1:
end_.append(start_[-1])
start_.remove(start_[-1])
print(self)
else:
self.Hanoi(n-1,start_,end_,inter_)
self.Hanoi(1,start_,inter_,end_)
self.Hanoi(n-1,inter_,start_,end_)
def __str__(self):
return 'start_peg, inter_peg, end_peg :{}t{}t{}'.format(self.A,self.B,self.C)
def get_pegs(self):
return self.A,self.B,self.C
#h=Hanoi(list(range(3,0,-1)))
h=Hanoi([3,2,1])
h.go()
A,B,C= h.get_pegs()
print(A,B,C)
Out:
start_peg, inter_peg, end_peg :[3, 2] [] [1]
start_peg, inter_peg, end_peg :[3] [2] [1]
start_peg, inter_peg, end_peg :[3] [2, 1] []
start_peg, inter_peg, end_peg :[] [2, 1] [3]
start_peg, inter_peg, end_peg :[1] [2] [3]
start_peg, inter_peg, end_peg :[1] [] [3, 2]
start_peg, inter_peg, end_peg :[] [] [3, 2, 1]
[] [] [3, 2, 1]