汉诺塔是一个非常经典的递归问题。
解决这种递归问题,从最简单的情况开始着手。
设现在有三个位置,分别是起始位置,过渡位置,目标位置。
假设 n = 1,那么直接一步就可以了。
n = 2 时,我们需要把起始位置上面的小的一块先放到 过渡位置,然后把大的一块放到目标位置。再把小的放到大的上去。
n = 3 时,........
可以看到,要想把起始位的最大块放大目标位,必须把它前 n-1 块放到过渡位置上,然后把最大块移动到目标位,再把n-1块移动到目标位,完成。
f(n) 代表把n块从一个位置移动到另一个位置上所需要操作的次数。
n | 过程 | 次数 |
1 | 1 | 1 |
2 | 1+1+1 | 3 |
3 | 3+1+3 | 7 |
4 | 7+1+7 | 15 |
..... | ...... | ..... |
n-1 | f(n-2)+1+f(n-2) | f(n-1) |
n | f(n-1)+1+f(n-1) | f(n) = 2*f(n-1)+1 |
程序如下。
其中参数部分,n 代表需要移动的块数, a 代表起始位置,b 代表过渡位置,c 代表目标位置。
//输出移动过程
hanoi( int n, char a, char b, char c){
if(n ==1 )//结束条件
printf("%c --> %c", a, c);
else{ //递归体
hanoi(n-1, a, c, b);
printf("%c --> %c", a, c);
hanoi(n-1, b, a, c);
}
}
hanoi( 5 , 'A', 'B', 'C');
//计算移动次数
hanoi( int n, char a, char b, char c){
if(n ==1 )//结束条件
return 1;
else{ //递归体
return 2*hanoi(n-1, a, c, b) + 1;
}
}