设A,B,C是三个塔座。开始时,在塔座A上有一叠共n个圆盘,这些圆盘自上而下,由大到小地叠在一起,各圆盘从小到大编号为1,2,。。。,n。现要求将塔座A上的这一叠圆盘移到塔座B上,并仍按同样顺序叠置。在移动圆盘时应遵守以下移动规则:
规则(1)每次只能移动一个圆盘;
规则(2)任何时刻都不允许将较大的圆盘压在较小的圆盘之上;
规则(3)在满足移动规则(1)和(2)的前提下,可将圆盘移至A,B, C中任一塔座上。
这个问题有一个简单的解法。假设塔座A、B、C排列成一个三角形,A——>B——>C——>A构成一顺时针循环。在移动圆盘的过程中,若是奇数次移动,则将最小的圆盘移到顺时针方向的下一塔座上;若是偶数次移动,则保持最小的圆盘不动。而其他两个塔座之间,将较小的圆盘移到另一塔座上去。
上述算法简洁明确,可以证明它是正确的。下面用递归技术来解决同一问题。
当n=1时,问题比较简单。此时,只要将编号为1的圆盘从塔座A直接移至塔座B上即可。
当n>1时,需要利用塔座C作为辅助塔座。此时设法将n-1个较小的圆盘依照移动规则从塔座A移至塔座C,然后,将剩下的最大圆盘从塔座A移至塔座B,最后,再设法将n-1个较小的圆盘依照移动规则从塔座C移至塔座B。
这样一来,n个圆盘的移动问题就可分解为两次n-1个圆盘的移动问题,我们又可以递归地用上述方法来做。
void Hanoi(int n,int A,int B,int C) { if(n>0) { Hanoi(n-1,A,C,B); Move(n,A,B); Hanoi(n-1,C,B,A); } }
其中,Hanoi(n,A,B,C)表示将塔座A上自下而上,由大到小叠在一起的n个圆盘依移动规则移至塔座B上并仍按同样顺序叠排。在移动过程中,以塔座C作为辅助塔座。
Move(n,A,B)表示将塔座A上编号为n的圆盘移至塔座B上。
Hanoi塔问题的非递归算法描述
void hanoi(int n) { int top[3]={0,0,0}; int **tower; Make2DArrary(tower,n+1,3);//生成二维数组 int b,bb,x,y,min=0; for(int i=0;i<=n;i++) { tower[i][0]=n-i+1; tower[i][1]=n+1; tower[i][2]=n+1; } top[0]=n;b=odd(n);bb=1; while(top[1]<n) { if(bb) { x=min; if(b) y=(x+1)%3; else y=(x+2)%3; min=y;bb=0; } else { x=(min+1)%3;y=(min+2)%3;bb=1; if(tower[top[x]][x]>tower[top[y]][y]) Swap(x,y); } move(tower[top[x]][x],x+1,y+1); tower[top[y]+1][y]=tower[top[x]][x]; top[x]--;top[y]++; } }
下面对非递归算法进行模拟
下面用数数归纳法证明递归算法和非递归算法产生相同的移动序列。
当n=1和n=2时容易直接验证。设当k<=n-1时,递归算法 和非递归算法产生完全相同的移动序列。考察k=n的情形。
将移动分为顺序时针移动(C)、逆时针移动(CC)和非最小圆盘塔座间的移动(O)三种情况。
当n为奇数时,顺时针非递归算法产生的移动序列为C,O,C,O,...,C;逆时针非递归算法产生的移动序列为CC,O,CC,O,...,CC。
当n为偶数时,顺时针非递归算法产生的移动序列为CC,O,CC,O,...,CC;逆时针非递归算法产生的移动序列为C,O,C,O,...,C。
(1)当n为奇数时,顺时针递归算法hanoi(n,A,B,C)产生的移动序列为
hanoi(n-1,A,B,C)产生的移动序列,O,hanoi(n-1,C,B,A)产生的移动序列。
其中,hanoi(n-1,A,C,B)和hanoi(n-1,C,B,A)均为偶数圆盘逆时针移动问题。由数学归纳法知,它们产生的移动序列均为C,O,C,O,...,C。因此,hanoi(n,A,B,C)产生的移动序列为C,O,C,O,...,C。
(2)当n为偶数时,顺时针递归算法hanoi(n,A,B,C)产生的移动序列为
hanoi(n-1,A,C,B)产生的移动序列,O,hanoi(n-1,C,B,A)产生的移动序列
其中,hanoi(n-1,A,B,C)和hanoi(n-1,C,B,A)均为奇数圆盘逆时针移动问题。由数学归纳法知,它们产生的移动序列均为CC,O,CC,O,...,CC。因此,hanoi(n,A,B,C)产生的移动序列为CC,O,CC,O,...,CC。
当n为奇数和偶数时的逆时针递归算法也类似。
由数学归纳法可知,递归算法和非递归算法产生相同的移动序列。