1.例题

题目:用递归解决汉诺塔问题(把n个盘子从A柱子移到C柱子,每次只能移动一个盘子,在任何时候,任何柱子上的盘子都是大盘在上,小盘在下)。

2.详细解析

(1)动画直观感受一下

【B站:悟道小番薯】汉诺塔问题动画

(2)描述

你看到了吗?
动画中有<mark>六块盘子</mark>,我们将<mark>三根柱子</mark>从左到右分为<mark>A,B,C</mark>,从上到下的盘子分为:<mark>1到6</mark>。

解决问题的思路是这样子的:

,先看<mark>最下面的一块盘子</mark>,它想的是
(1)只要在它上面的盘子先从A移到B,
(2)它在从A移到C,
(3)最后那五块盘子再从B移到C,那就完成任务了吗!

于是,它下了两条命令(从动画中可以证明:命令是可以被执行的):
第一条:1到5的盘子从A移到B
第二条:1到5的盘子从B移到C

,再看<mark>第二块盘子</mark>的想法:(这里插一句话:6块盘子从A移到C,和5块盘子从A移到B,5块盘子从B移到C的要求是不是差不多,只是少了一块盘子而已)
<mark>要完成第一块盘子交给的(第一个)任务:</mark>
(1)只要在它上面的盘子先从A移到C,
(2)它在从A移到B,
(3)最后那四块盘子再从C移到B,那就完成任务一(1到5的盘子从A移到B)了吗!
<mark>要完成第一块盘子交给的(第二个)任务:</mark>
(1)只要在它上面的盘子先从B移到A,
(2)它在从B移到C,
(3)最后那四块盘子再从A移到C,那就完成任务二(1到5的盘子从B移到C)了吗!


你发现了吗?最下面的盘子和第5个盘子的任务是差不多一样的:

<mark>除了第一块盘子,所有的盘子都想先让在它上的盘子移到另外的柱子上,自己再移到目标柱子,最后让其他柱子回到目标柱子上。</mark>

这就是<mark>递</mark>的思想:要完成6个盘子从A移到C,你先把前5个盘子的任务做好;
要想把前5个盘子的任务做好,你先把前4个盘子的任务做好;
要想把前4个盘子的任务做好,你先把前3个盘子的任务做好;


你先把第1个盘子的任务做好。

这是<mark>归</mark>的思想:你把第1个盘子移好了,我就能把前两个盘子移好;
这样我就能把前三个盘子移好;


我就能把6个盘子移好。

(3)代码

一.分块解析

这是将盘子移动的函数

void move(char X, char Y)
{
   
    cout << X << " ——> " << Y << endl;
}

这就是汉诺塔的函数了,一个函数中调用自身的函数叫做递归函数,<mark>else</mark>里面是递的思想,<mark>if</mark>里面是归的思想,hanoi函数能实现把n个盘子从A柱子移到C柱子上。

<mark>hanoi(n - 1, A, C, B)</mark>:这句话不简单,它的意思是第n-1块盘子要完成的第一个任务:把n-1个盘子从A盘移到B盘。
它调用的也是hanoi函数,它把<mark>A装进char A这个桶子里,把C装进char B这个桶子里,把B装进char C这个桶子里</mark>,当它<mark>实现move(A,C)这个语句</mark>时是把第n-1块盘子从A柱子移到B柱子上的,同理,其他也是一样的(不要被它的外表所迷惑!)。

void hanoi(int n, char A, char B, char C)//这相当于桶子
{
   
    if (n == 0)
        return;
    else
    {
   
        hanoi(n - 1, A, C, B); //这就是任务一,把在目前的盘子上面的盘子移到其他柱子上
        move(A, C);            //将目前的盘子移到目标柱子上
        hanoi(n - 1, B, A, C); //最后将其他盘子移到目标柱子上
    }
}

这是主函数

int main()
{
   
    int n;
    cout << "请输入A柱子上的盘子数目:";
    cin >> n;

    hanoi(n, 'A', 'B', 'C');//调用hanoi函数

    return 0;
}

二.完整代码

#include <iostream>
using namespace std;
void move(char X, char Y)
{
   
    cout << X << " ——> " << Y << endl;
}
void hanoi(int n, char A, char B, char C)
{
   
    if (n == 0)
        return;
    else
    {
   
        hanoi(n - 1, A, C, B); 
        move(A, C);            
        hanoi(n - 1, B, A, C); 
    }
}
int main()
{
   
    int n;
    cout << "请输入A针上的盘子数目:";
    cin >> n;
    hanoi(n, 'A', 'B', 'C');
    return 0;
}

最后我想说的是,这是我的【C++练习系列】的第四篇文章,喜欢的话希望可以点一下赞,并关注我的前面三篇文章,ok,再见啦。