《C语言大学教程(第八版)》第五章 课后习题 5.36参考答案

文章讲述了作者在解决汉诺塔问题时对递归理解的深化过程,从最初的认为递归必须有return返回值,到通过实际操作和书籍学习理解到递归的核心在于抽象和递归调用,而非返回值。通过汉诺塔问题的解决,演示了如何运用递归思想,即使没有返回值也能实现递归功能,强调了独立思考和解决问题能力的重要性。
摘要由CSDN通过智能技术生成

前言
  这道题目,是一次对递归理解的跨越。友情提示,解决这道题目,首先要确保时间足够,其次要有耐心。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
解析
  要想解这道题,绝对是智力的一次提升。
  话不多说,先回顾本书对递归的讲解以及例题。
  当我第一次学习书中递归的概念时,通过书中两处对递归的阐述,进入了一种定势思维,认定递归必须要有return返回值,即认为习题5.36的递归中,也都必须要有return返回值。如下图所示:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
  同时,结合书中所讲到的两个示例:递归地计算阶乘和斐波那契数列,在给出的对应示例代码中,都包含有return返回值,这进一步加深了上述定势思维,认定递归必须要有return返回值。如下图所示:
  
递归地计算阶乘
在这里插入图片描述
  
斐波那契数列
在这里插入图片描述
在这里插入图片描述
  可是,当我带着递归必须要有return返回值的定势思维,去尝试解决习题5.36时,我发现自己无从下手,甚至对自己产生了质疑,一度陷入了巨大的痛苦之中。
  绞尽脑汁,依然没有任何思路,不得不在网上找寻相关的信息。这里,有的小伙儿伴可能会问,为什么不直接去问chatgpt呢,还在网上搜什么呀,多麻烦。还是那句话,chatgpt可以直接给出答案。我想要培养的是一种思考问题、解决问题的能力,如果事事都直接问chatgpt,到最后就会成为chatgpt的奴隶,对chatgpt产生依赖,一旦离开chatgpt,你什么也不会了,这不是我想要的。
实际体验汉诺塔
  因为,这道题目已经讲解了什么是汉诺塔。但是,我在实际生活中并没有玩过汉诺塔。所以,我就找了一张方形的纸,对折两次后,用手撕开,得到四个方形小纸片。然后,再把其中的三个方形小纸片,按照不同程度进行边缘折叠。最终,我得到了四个大小不一的方形纸片。以此,模拟出了四层汉诺塔。
  先从一层汉诺塔开始,这个非常简单,只需要一步,直接从起始第一处移动到目标第三处即可。如下图所示:
在这里插入图片描述
  再来看二层汉诺塔,这个就需要三步来完成了,如下图:
在这里插入图片描述
在这里插入图片描述
  接着看三层汉诺塔,这个就需要七步来完成了,如下图:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
  四层汉诺塔,就需要15步来完成了,如下图所示:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
  我想,当你第一遍看到这里时,估计已经凌乱了,多少会出现,眼睛看明白了,脑子也想明白了。但是,自己动手实际操作,恐怕无法熟练清晰的完成。这是很正常的,不必惊慌。
  我们接着来分析,一层汉诺塔需要1步,二层汉诺塔需要3步,三层汉诺塔需要7步,四层汉诺塔需要15步。可以得到里面的规律是2的n次方减1,也即是说五层汉诺塔需要31步,六层汉诺塔需要63步。
  2020年8月3日,夏焱以33.039秒的成绩成功打破6层汉诺塔吉尼斯世界纪录。
  2021年5月16日,中国龙岩的陈诺以29.328秒的成绩打破了6层汉诺塔吉尼斯世界纪录。
  通过以上的信息,对汉诺塔有了一些更多的了解,这让我们对汉诺塔不再那么的有距离感。可是,明白了这些,对于如何解决习题5.36貌似没有直接性的帮助。而且,题目中这一段提示性的话,对于一张白纸的初学者来说,依然没有建立起理解性的链接。简言之,无法使用提示信息来完成这道题目。如下图所示:
在这里插入图片描述
求解
  正是如此,陷入了更加的痛苦之中。感觉这道题目和书中讲解到的知识点,跨度太大,一时间,无能为力。于是,在网上几经搜寻,找到了《程序设计抽象思想:C语言描述》。在这本书的第四章,作者提出了对递归思想的一些阐述和建议,对于初学者具有相当的意义。下面节选一部分,分享给大家:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
  在《程序设计抽象思想:C语言描述》这本书中,第五章,有关于汉诺塔递归的详细解读。注意,在这本书的讲解中,是把汉诺塔从第一个柱子最终移动到第二个柱子。而在我们要解决的习题5.36,是把汉诺塔从第一个柱子最终移动到第三个柱子。虽然,有这个移动的区别。但是,这完全不会影响我们理解。因为,一旦你理解了其中的思想,往哪根柱子移动都是形式在变,本质不变。甚至,起始点不在第一根柱子,也都一样。
  下面的节选,以快速阅读的方式进行,不要纠结其中。我在后面,会以非常生动形象的图画来总结说明,非常容易理解。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
  上述的节选,真正的核心就只有一句话:抽象。不管是多少层的汉诺塔,都把其抽象为二层汉诺塔。比如,有n层汉诺塔,最下面那一层为第n层,上面的n-1层抽象为一层。这样,就完成了递归的思想。
在这里插入图片描述  所以,抽象之后,汉诺塔的递归重复模式,只有三步:
在这里插入图片描述
  上面这三句话,是不是和我们这道题目的三句话很像呢:
在这里插入图片描述
  到这里,可能,你还是混乱不清。但是,最起码,你要有所领悟了。如果还是一点儿领悟也没有,下面是我在另一部书中看到的相关建议:离开计算机,先休息一会儿再尝试。请懂得人来帮你。到网上寻求帮助。
  接下来,我们需要看一下递归的具体过程。切记,这里容易出现混乱,你只需要记住else语句里面有三行代码,第一行代码本身,就已经开始递归了。当第一行代码执行完毕后即递归完毕后,就会继续执行else语句里面的第二行代码。当第二行代码执行完毕后,就会执行else语句里面的第三行代码,第三行代码本身,也开始递归。当第三行代码执行完毕后即递归完毕后,程序即结束,汉诺塔也随即完成全部移动。

...
	else
	{
		MoveTower(n - 1, start, temp, finish);    //第一行代码
		MoveSingleDisk(start, finish);            //第二行代码
		MoveTower(n - 1, temp, finish, start);    //第三行代码
	}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述  在进行了如此这般的铺垫后,开始着手于习题5.36,直接上代码。

#include <stdio.h>

void towerhanoi(int num, int start, int goal, int temporary);

int main()
{
    int i;

    towerhanoi(3, 1, 3, 2);
}

void towerhanoi(int num, int start, int goal, int temporary)
{
    if (num == 1)
    {
        printf("%d -> %d\n", start, goal);
    }
    else
    {
        towerhanoi(num - 1, start, temporary, goal);
        printf("%d -> %d\n", start, goal);
        towerhanoi(num - 1, temporary, goal, start);
    }
}

  你没有看错,这么大一番折腾,代码就这几行即可,无需复杂。
  现在,来解释上述代码:
  下面这一段代码,是用来处理最简单的情况,当汉诺塔为一层时,直接打印即可。

    ...
    if (num == 1)
    {
        printf("%d -> %d\n", start, goal);
    }
    ...

  下面这一段代码,有用来处理多层汉诺塔的情况。

    ...
    else
    {
        towerhanoi(num - 1, start, temporary, goal);
        printf("%d -> %d\n", start, goal);
        towerhanoi(num - 1, temporary, goal, start);
    }

  其中,第一行代码的作用,把上面n-1层抽象为1层并先移动到临时的柱子。对应两本书中提到的话:
在这里插入图片描述
在这里插入图片描述

...
towerhanoi(num - 1, start, temporary, goal);
...

  第二行代码的作用,是把最下面的第n层,直接从起始位置移动到目标位置。对应两本书中提到的话:
在这里插入图片描述
在这里插入图片描述

...
printf("%d -> %d\n", start, goal);
...

  注意,这一步,不管是几层汉诺塔,都是固定的操作,把最下面那一层移动到目标位置。所以,直接打印即可,无需再调用自身函数进行递归。
  第三行代码的作用,是把移动到临时柱子的n-1层(已抽象为1层),移动至目标柱子。对应两本书中提到的话:
在这里插入图片描述
在这里插入图片描述

...
towerhanoi(num - 1, temporary, goal, start);
...

  三行代码,对应三步操作。
  至此,完成汉诺塔递归。
  当你走到这一步的时候,就能知晓,无论汉诺塔是以第几根柱子开始,移动至第几根柱子结束,你都可以进行递归。因为,其中设计的递归思想是一致的,万变不离其宗。
  ok,我们回过头来,好好捋一下。最初遇到的问题是,书中讲到关于递归,必须要有return返回值。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
  然后,书中的两处示例,递归地计算阶乘和斐波那契数列,给到的代码也都有return返回值。
  递归地计算阶乘
在这里插入图片描述
  斐波那契数列
在这里插入图片描述
在这里插入图片描述
  这里,容易自己误导自己,导致思维定式的产生,认为所有的递归都必须包含return返回值。
  当经历了这一切,甚至有些怀疑,作者这样安排学习的难度,跨度是否有些大,中间是否缺少了一些铺垫呢。于是,我去查阅了《C语言大学教程(第八版)》的英文原版,仔细对比这一章节的内容和课后习题,发现相关涉及到的内容一致。我不禁感慨,学无止境,每完成一道难题的学习,能够更深刻感觉到自身的渺小,内心的浮躁和骄傲也都少了一分,还得是保持一颗谦卑的心态啊。加油,共勉!

MDK 5.36的安装教程如下: 1. 首先,下载MDK 5.36的安装文件。你可以在官方网站上下载,或者在一些第三方网站上找到可靠的下载链接。 2. 打开下载的安装文件,运行MDK.EXE文件开始安装。 3. 安装过程中,按照提示选择安装路径和其他选项。你可以选择默认设置,或者根据自己的需求进行自定义设置。 4. 安装完成后,打开Keil MDK集成开发环境。在菜单栏中找到"File",然后选择"Licence Management"。 5. 在弹出的窗口中,复制计算机ID(CID),这是用来生成密钥的唯一标识符。 6. 下载一个注册机(也称为密钥生成器),并打开它。将CID粘贴到注册机中,并点击"Generate"生成新的许可证ID码(LIC)。 7. 将生成的LIC粘贴到Keil MDK的Licence Management窗口中,然后点击"Add LIC"。 8. 安装所需的芯片支持包。你可以从芯片官方网站下载支持包,或者在Keil MDK中添加支持包。 9. 打开Keil MDK,检查是否成功添加了芯片的集成包。 现在,你已经成功安装了MDK 5.36,并可以开始使用它来建立项目和进行开发工作了。祝你工作愉快! #### 引用[.reference_title] - *1* [蓝桥杯嵌入式CT117E-M4学习笔记03-MDK环境安装](https://blog.csdn.net/A5wa41s/article/details/128747748)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [如何安装keil](https://blog.csdn.net/weixin_44006573/article/details/112308647)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [Keil MDK 5.36安装及和谐](https://blog.csdn.net/13011803189/article/details/124693746)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值