题目:相邻三根柱子,分别为A(源),B(备用),C(目标)。将A上的n个盘子移动到C上。
限制条件:
在小圆盘上不能放大圆盘。
在三根柱子之间一回只能移动一个圆盘。
只能移动在最顶端的圆盘。
方法一:递归方法。
算法:
1)当A上的盘子数量为1时,直接将盘子移动到C 柱子上。
2)当A上的盘子数量大于1时,先将A上的第1到n-1个盘子借助C,移动到B上。
然后将第n个盘子移动到C上,
再讲B上的n-1个盘子借助A移动到C上。
代码:

move(int n,char from,char to)
{
  cout <<"move "<<n<<" from "<< from << " to "<< to<<"!\n";
}
void hanoi(int n,char from,char depend_on,char to)
{
    if(n==1)
        move(1,from,to);
     else 
     {
          hanoi(n-1,from,to,depend_on);
          move(n,from,to);
          hanoi(n-1,depend_on,from,to);
     }
}
int main(void)
{
    int num;
    cout<<"please input numbers of panzi!"<<endl;
    cin >> num ;
    cout << "num=" <<num;
    hanoi(num,'A','B','C');
    cout <<"move "<<i <<"times!\n"<<endl;
    return 0;
}

当n=1,需要移动1次,当n=2,时需要移动3次,当n=10次时,需要移动1023次,当n=i次时,需要移动2^-1次。

方法二:用非递归实现
非递归算法:
定义从小到大的盘子序号分别为1,2,……n。
可以用一个1到2^n - 1的2进制序列可以模拟出n个盘子的汉诺塔过程中被移动的盘子的序号序列。
即给定一个n,我们通过0到2^n - 1序列可以判断出任意一步应该移动那个盘子。
判断方法:第m步移动的盘子序号是m用二进制表示的最低位bit为1的位置。

证明: n = 1,显然成立。
假设n = k 成立。
n = k + 1时,对应序列1到2^(k+1) - 1,显然这个序列关于2^k左右对称。
假设我们要把k + 1个盘子从A移动C。
那么2^k可以对应着Move(k + 1, A, C)。 1 到 2^k - 1 根据假设可以
对应Hanoi(A, B, C, k)。至于2^k + 1 到 2^(k + 1) - 1把最高位的1去掉对应序列变成1到2^k - 1,显然2^k + 1 到 2^(k + 1) - 1和1到2^k - 1这两个序列中的对应元素的最低位bit为1的位置相同。因此2^k + 1 到 2^(k + 1) - 1可以对应Hanoi(B, C,A,k)。
所以对n = k + 1也成立。

下面讨论第m步应该移动对应的盘子从哪到哪?
定义顺序为 A->B->C->A, 逆序为C->B->A->C。

性质对n个盘子的汉诺塔,任意一个盘子k(k <= n)k在整个汉诺塔的移动过程中要么一直顺序的,要么一直逆序的。而且如果k在n个盘子移动过程的顺序和k - 1(如果k > 1)以及k + 1(如果k < n)的顺序是反序。

比如:n = 3
1 A->C
2 A->B
1 C->B
3 A->C
1 B->A
2 B->C
1 A->C
其中1的轨迹A->C->B->A>C逆序,2的轨迹A->B->C顺序,3的轨迹A->C逆序

证明:假设n <= k成立
对于n = k + 1 根据递归算法
Hanoi(A,C,B,k + 1) = Hanoi(A, B, C, k) + Move(A, C, k + 1) + Hanoi(B, C,A,k);
整个过程中盘子k + 1只移动一次A->C为逆序对应着2^k。
对于任意盘子m < k + 1,
m盘子的移动由两部分组成一部分是前半部分Hanoi(A, B, C, k)以及后半部分的Hanoi(B, C,A,k)组成。显然有如果m在Hanoi(A, C, B, k)轨迹顺序的话,则m在Hanoi(A, B, C, k)以及Hanoi(B, C,A,k)都是逆序。反之亦然。这两部分衔接起来就会证明m在Hanoi(A,C,B,k)和Hanoi(A,C,B,k + 1)中是反序的。
同时有Hanoi塔中最大的盘子永远是逆序且只移动1步,A->C。
这样的话:
m = k + 1,在Hanoi(A,C,B,k + 1)中是逆序。
m = k,由于在Hanoi(A,C,B,k)中是逆序的,所以Hanoi(A,C,B,k + 1)中是顺序的。
m = k - 1,由于在Hanoi(A,C,B,k - 1)是逆序的,所以Hanoi(A,C,B,k)是顺序的,所以Hanoi(A,C,B,k + 1)是逆序的。
依次下去……
结论得证。
总结:在n个汉诺中n, n - 2, n - 4……是逆序移动,n - 1, n - 3,n - 5……是顺序移动。

有了以上结论,非递归的程序就很好写了。写了个递归和非递归比较程序:

include

using namespace std; 
 void Hanoi(char src, char des, char via, int n) 
 { 
 if(n == 1) 
 { 
 cout << n <<” : “<< src <<” –> ” <