使用Python编写的河内塔,使用列表打印每个步骤。但我不想使用全局变量

时间:2018-08-25 05:16:28

标签: python python-3.x

代码说明:输入n为整数,其他输入为list(降序)。例如n=3A=list(range(n,0,-1))B=[]C=[](较大的整数表示较大的光盘)。

下面的代码有效,但是输入列表变量(start_inter_end_)的名称必须为AB,{{1} },因为Hanoi函数包含全局变量CAB。这很烦人。

如何用列表表示每个步骤而没有全局变量?换句话说,基本情况的操作(追加,删除)如何取决于输入位置而不是变量名。

例如:

C是第二个输入变量,start_是第四个输入变量。

基本情况操作->第四输入变量。append(第二输入变量[-1], 第二个输入变量.remove(第二个输入变量[-1])

end_

----(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(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]

3 个答案:

答案 0 :(得分: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可以使用它以一致的顺序将它们全部写出。

答案 1 :(得分:0)

  

如何用没有全局变量的列表表示每个步骤?

答案很简单。只需使用您传入的变量的名称即可:

print('start_peg , inter_peg, end_peg :{}\t{}\t{}'.format(start_, inter_, end_))

这就是python处理对象的方式。对象绑定到给定范围内的名称,但是可以在许多范围内命名。您可以将对象绑定到任意多个名称。

例如,假设您拥有(功能之外)

n = 3
A = list(range(n, 0, -1))
B = []
C = []

这些分配将四个不同的对象(int和三个list)绑定到四个不同的名称(nAB,{{ 1}})。现在,当您致电

C

将相同的四个对象绑定到函数名称空间中的名称Hanoi(n, A, B, C) nstart_inter_。无论您使用全局名称end_还是本地名称A,您都在引用内存中的同一对象。

在不相关的注释上,start_对值已知的对象执行不必要的按值搜索。由于您已经将值分配给了上面一行中的正确堆栈,因此执行删除操作的一种更简单的方法是

start_.remove(start_[-1])

一个更优雅的解决方案是将这两行替换为

del start_[-1]

答案 2 :(得分:-1)

您可以使用第一个元素为列表“命名”:

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]