字符串形式的汉诺塔(Tower of Hanoi)Python语言实现_18.6.19更新
代码优势:模块化做的很好,找到了通过写出前4-5次的数学表达,找到了规律并将其化成代码__18.6.19:昨天的程序将激励想复杂了,这里最简基例是搬1个汉诺塔,最初想复杂了想成了2个!导致if和else语段有重合内容,代码已更新,减少了几行,增加了计次功能!.
代码劣势:规则化欠佳,因python无指针(网上说的,还不确定),没有学到python中类似c语言指针的函数,造成本来一个模块不得不分解为6个模块相互调用.并且函数封装不好,即因为不会类指针方法,所以用函数操作了全局变量.
上代码1:
#这里最简基例是搬1个汉诺塔,最初想复杂了想成了2个 def ac(k): global a global b global c global count if k==1: c+=a[-1];a=a[:-1];count+=1 else: ab(k-1) c+=a[-1];a=a[:-1];count+=1 bc(k-1) def ab(k): global a global b global c global count if k==1: b+=a[-1];a=a[:-1];count+=1 else: ac(k-1) b+=a[-1];a=a[:-1];count+=1 cb(k-1) def cb(k): global a global b global c global count if k==1: b+=c[-1];c=c[:-1];count+=1 else: ca(k-1) b+=c[-1];c=c[:-1];count+=1 ab(k-1) def ca(k): global a global b global c global count if k==1: a+=c[-1];c=c[:-1];count+=1 else: cb(k-1) a+=c[-1];c=c[:-1];count+=1 ba(k-1) def ba(k): global a global b global c global count if k==1: a+=b[-1];b=b[:-1];count+=1 else: bc(k-1) a+=b[-1];b=b[:-1];count+=1 ca(k-1) def bc(k): global a global b global c global count if k==1: c+=b[-1];b=b[:-1];count+=1 else: ba(k-1) c+=b[-1];b=b[:-1];count+=1 ac(k-1) a='fedcba9876543210' b='' c='' count=0 ac(len(a)) print('a:{0}\nb:{1}\nc:{2}\ncount:{3}'.format(a,b,c,count))
输出为:
a:
b:
c:fedcba9876543210
count:65535
逻辑思维的结果为2^n-1,与计算思维的结果相同.也证明了这是最简单的方法.
F7一步步看了9层汉诺塔中a,b,c字符串的变换过程,发现代码至少在9层是正确的,20层的时候也和代码2相呼应计次为1048575,所以基本上可以确定算法是正确的.
举一反三:上述代码是字符串形式的汉诺塔,容量有限且处理16个以上元素时表示不方便,后面会写一个列表形式的汉诺塔
18.6.19日补充这个程序实现了汉诺塔搬运的仿真,当时刚看到题目就按下了暂停键,结果今天发现老师只实现了汉诺塔实现方法的打印,还是比较刁钻的,这很有启发性,在学习阶段探索仿真固然好,但商业化的项目中,设计算法前还是看清要求,因为如果只是要求给出汉诺塔实现方法则要简单许多,which只用一个模块使用print函数打印就行了!
下面给出打印汉诺塔实现方法的程序,这个类似于物理实现,要简单一点.
上代码2:
def f(a,b,c,k): global count if k==1: print('{0}->{1}'.format(a,c),end=';') count+=1 else: f(a,c,b,k-1) print('{0}->{1}'.format(a,c),end=';') count+=1 f(b,a,c,k-1) s='a' m='b' t='c' c=16 count=0 f(s,m,t,c) print('count:{0}'.format(count))
同代码1,实现16层汉诺塔搬运,这里count仍是65535,是正确的.
心得:要改变字符串(汉诺塔)的值,在不了解Python指针(还不知道有没有,暂时没学到)的情况下,不能将全局变量a,b,c作为函数的形参,所以必须用6个模块分别实现塔(列表或字符串)之间的塔层(元素)交换.而引入形参k是实现递归调用的关键,否则没有跳变的形参,递归就无从谈起.所以,在定义函数时,分清全局变量和局部变量,形参和实参的个数,极其关键!