最简单的汉诺塔实现就是递归,比如c语言的实现:
void move(char A,int n,char C){
printf("%d,%c,%c\n",n,A,C);
}
void Hanoi(int n,char A,char B,char C){
if(n==1) move(A, 1, C,m);
else{
Hanoi(n-1,A,C,B);
move(A, n, C);
Hanoi(n-1,B,A,C);
}
}
但是如果想给move函数打印的时候追加序号来显示移动盘子是第几次操作,则需要一个单独的变量用于计数,手头一本教材上非常简单的设置了一个全局变量,并把变量置于move函数中自增长。
所以在单线程程序里面,多次调用Hanoi(int n,char A,char B,char C),就得重置这个全局变量。
相关实现:
int m=0;
void move(char A,int n,char C){
printf("[%d]%d,%c,%c\n",++m,n,A,C);
}
void Hanoi_(int n,char A,char B,char C){
if(n==1) move(A, 1, C);
else{
Hanoi_(n-1,A,C,B);
move(A, n, C);
Hanoi_(n-1,B,A,C);
}
}
void Hanoi(int n,char A,char B,char C){
initHanoi();
Hanoi_(n,A,B,C);
}
void initHanoi(){//这个代码在多线程程序中一定会出问题
m=0;
}
在多线程程序中这个代码必定会出现问题的,如果给m加锁,它就和单线程没有区别了。这个问题最简单的处理方法就是闭包,让变量m只被Hanoi(int n,char A,char B,char C)访问的到,外部不能访问,并且每次调用它得到的m只是一个副本,它们的数据不会相互影响。
然而谷歌的结果是C语言不能像python那样的方法实现闭包,一定要写也可以,那是苹果公司在clang上面加上的闭包特性,只有clang编译器支持,clang的写法是不通用的。
python的闭包实现:
def Hanoi(n,A,B,C):
m=0
def move(A,n,C):
nonlocal m
m+=1
print("[%d]%d,%c,%c" %(m,n,A,C))
def Hanoi_(n,A,B,C):
if n==1:
move(A, 1, C)
else:
Hanoi_(n - 1, A, C, B)
move(A, n, C)
Hanoi_(n - 1, B, A, C)
Hanoi_(n,A,B,C)//闭包其实要写成 return Hanoi_,只是这里只需要调用一次
其实想想,C语言也能写出类似闭包的写法,只是要传参数而已:
void move(char A,int n,char C,int &m){
printf("[%d]%d,%c,%c\n",++m,n,A,C);
}
void Hanoi_(int n,char A,char B,char C,int &m){
if(n==1) move(A, 1, C,m);
else{
Hanoi_(n-1,A,C,B,m);
move(A, n, C,m);
Hanoi_(n-1,B,A,C,m);
}
}
void Hanoi(int n,char A,char B,char C){
int m=0;
Hanoi_(n,A,B,C,m);
}
有点闭包的味道了,23333333
----------------------------------------------------------
我这些写法并不是完整严格的闭包概念,不过闭包目前对我而言只是不去给变量加锁的偷懒方法而已,先这样吧。
闭包定义的讨论:https://www.ibm.com/developerworks/cn/linux/l-cn-closure/
根据该文章的说法,闭包和返回函数也没有必然关系,看来也只是一种形式而已,闭包的有一层意义是函数执行完成之后,它的成员变量不会被回收,因为这个变量要给函数返回的函数去执行。而我只是用了它另一个作用,每次调用函数,内部函数相当于使用的是外部变量的副本,这样就能避免数据相互影响,这也是类似一种包啊。
为了写闭包而闭包是没有必要的,要关注的是闭包的实际服务作用,按实际需要而写。