【C语言】递归详解汉诺塔问题

article/2025/9/7 22:18:24

文章目录

  • 前言
  • 汉诺塔移动图解
  • 汉诺塔移动次数
  • 汉诺塔的打印
  • 结语

如果无聊的话,就来逛逛 我的博客栈 吧! 🌹

前言

汉诺塔,是一个源于印度古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。当把64片圆盘从第一根石柱移动到第三根石柱时,这个世界就会毁灭。

而婆罗门移动圆盘需要用多长时间呢?通过平常的方法是很难计算的。

今天我们就利用递归的思想来计算一下汉诺塔的移动次数和汉诺塔的移动步骤!

汉诺塔移动图解

汉诺塔移动的规律为一次只能移动一个圆盘,并且小盘要在大盘的上方,假设在A柱有n个圆盘,我们先要把n-1个圆盘从A柱移动到B柱,再把第n个圆盘移动到C柱,最后把n-1个圆盘移动到C柱。

以三阶汉诺塔为例:
image-20220706104745915

image-20220706105031319

汉诺塔移动次数

利用穷举的办法,对于汉诺塔的移动次数进行计算:

阶数次数规律
112^1-1
232^2-1
372^3-1
4152^4-1
2^n-1

对于n阶汉诺塔的移动次数:

  • 步骤1所含步数就是n-1个圆盘移动所需的次数,我们可以将其步数看做f(n-1)。
  • 步骤2所含步数为1。
  • 步骤3所含步数与步骤1相似,我们也将其步数看做f(n-1)。

再观察表格中汉诺塔的移动次数,对于一阶汉诺塔移动次数就为1,对于其他的阶数则为前一阶汉诺塔移动次数 + 1 + 前一阶汉诺塔移动次数。

不难得出递推表达式:f(n-1) + 1 + f(n-1) = 2 * f(n - 1) + 1

移动步骤符合递归思想,代码展示:

#include<stdio.h>
int hanoi_step(int n)
{if(n<=1)return 1;elsereturn 2*hanoi_step(n-1)+1;
}
int main()
{int n = 0;scanf("%d",&n);int ret = hanoi_step(n);printf("%d\n",ret);return 0;
}

运行结果:

image-20220706115426701

汉诺塔的打印

这里的打印指的是打印汉诺塔移动的步骤。

我们可以先尝试写出1-4阶汉诺塔的移动步骤:

阶数步骤
1A->C
2A->B,A->C,B->C
3A->C,A->B,C->B,A->C,B->A,B->C,A->C
4A->B,A->C,B->C,A->B,C->A,C->B,A->B,A->C,B->C,B->A,C->A,B->C,A->B,A->C,B->C

我们观察移动步骤,发现只有一个圆盘时移动步骤为A->C;两个圆盘时,为A->B,A->C,B->C。

那么对于n阶汉诺塔呢,我们对其进行推演:

  • 把n-1个圆盘从A移动到B
  • 把第n个圆盘从A移动到C
  • 把n-1个圆盘从B移动到C

那n-1个圆盘如何从A移动到B呢?

  • 把n-2个圆盘从A移动到C
  • 把第n-1个圆盘从A移动到B
  • 把n-2个圆盘从C移动到B

同样的,对于把n-1个圆盘从B移动到C,也可以推测出来:

  • 把n-2个圆盘从B移动到A
  • 把第n-1个圆盘从B移动到C
  • 把n-2个圆盘从A移动到C

通过这些推演我们发现,汉诺塔的移动可以通过递归展开,那么以上推演步骤,我们可以将其作为递归的步骤。

思路:定义A,B,C三个字符,表示A,B,C三柱,定义n为阶数,那么n-1也就是移动步骤中,需要移动的圆盘数。
对于一阶汉诺塔,直接移动即可,对于其他的阶数,则需要通过递归展开,为n阶汉诺塔的移动步骤。

#include<stdio.h>
void hanoi_move(int n,char A,char B,char C)
{if(1==n){printf("%c->%c\n",A,C);}else{hanoi_move(n-1,A,C,B);//将n-1个圆盘从A移动到Bprintf("%c->%c\n",A,C);//将第n个圆盘从A柱移动到C柱hanoi_move(n-1,B,A,C);//将n-1个圆盘从B柱移动到C柱}
}
int main()
{int n = 0;scanf("%d",&n);hanoi_move(n,'A','B','C');return 0;
}

只通过代码可能不太直观,我们以三阶汉诺塔为样例,观察递归是如何展开的:
image-20220725083935628

运行结果:

image-20220706144428116

结语

了解了汉诺塔的移动步数和过程,我们也可以对64片黄金圆盘移动完需要的时间做一个估算,将每次移动看作一秒,那么时间为:2 ^ 64 - 1 = 18,446,744,073,709,551,615秒,换算成年数,约为5800亿年。

按照这个进度,到时候世界毁灭也是有可能的,只是可怜了“悲惨的婆罗门”需要移动这些圆盘(doge)。

以上就是C语言递归求解汉诺塔的全部内容,如果觉得anduin写的还不错的话,还请一键三连!

我是anduin,一名C语言初学者,我们下期见!


http://chatgpt.dhexx.cn/article/6uL0Ykaa.shtml

相关文章

Linux基本操作---实践+理解--CentOS 7

目录 CentOS系统ls查看信息cd目录切换文件操作系统关闭/重启防火墙操作 CentOS系统 Linux系统有很多&#xff0c;常见的Linux系统有乌班图&#xff08;Ubuntu&#xff09;、深度&#xff08;deepin&#xff09;、CentOS等等&#xff0c;CentOS 7 是目前比较流行的Linux操作系统…

Linux 文件操作基本命令

在Linux文件操作中&#xff0c;最常用的基本命令包括&#xff1a;打开或者创建文件&#xff0c;写入文件&#xff0c;读取文件 下面将依次介绍这几种操作的常用方法。 1.打开/创建文件 首先说明在VI编辑模式中&#xff0c;若要使用该API&#xff0c;需包含相应的头文件&…

Linux基本操作命令 实验

一、实验目的&#xff1a; 1. 熟悉Linux基本命令。 2. 熟悉Linux操作系统。 二、实验环境&#xff1a; 一台装有Linux的机器。 三、实验内容&#xff1a; 1.文件操作命令的使用。 用vi编辑器新建一个testl文件 输入this is testl~&#xff01; 查看文件与目录ls 进入…

linux的基本操作命令

1.使用timedatectl查看时间状态 列出所有已知时区 修改时区为列出时区的某一个 首先打开linux系统&#xff0c;进入管理员模式&#xff0c;输入timedatectl [rootroot ~]# timedatectl Local time: Sun 2022-03-20 17:26:05 CSTUniversal time: Sun 2022-03-20 09:26:05 …

Linux实验一:熟悉Linux基本命令

【实验目的】 ‏(1)熟悉常用的文件和目录类命令。 ‏(2)熟悉常用的进程管理类命令。 ‎ ‏【实验要求】 ‎ 本实验的主要任务是在Linux终端窗口中练习已经学过的各种命令&#xff0c;熟练掌握常用命令的用法。清大家按照以下步骤完成本次实验。 ‏(1)以普通用户登录系统&…

linux配置网口的ip地址,Linux基本操作和基础命令(Linux修改IP地址以及修改网卡地址)...

Linux基本操作和基础命令(Linux修改IP地址以及修改网卡地址) 今天博主和大家聊一聊 Linux的基本操作&#xff0c;不喜勿喷&#xff0c;如有建议欢迎补充&#xff0c;讨论。 一.Linux网络 1.网卡的命名规则 CENTOS7采用dmidecode采集命名方案&#xff0c;以此来得到主板信息&…

Linux基本命令及编程环境实验

目录 一、Linux基本命令详细汇总 1、目录及文件相关命令 2、系统信息查询 3、文件操作&#xff08;统计、过滤、搜索、权限&#xff09; 4、其他命令 二、Linux终端上vi命令编程 1、进入vi命令模式 2、vi编辑模式 3、最后行模式 4、vi 编辑C源程序并编译运行 最后 一…

linux基本命令大全

基本命令 关机&#xff1a;shutdown -h halt init 0 poweroff 重启&#xff1a;shutdown -r reboot init 6 pwd&#xff1a;查看工作目录 ls&#xff1a;查看指定目录的内容 -l&#xff1a;列表显示 -a&#xff1a;显示所有&#xff0c;包括隐藏文件 -h&#xff1a;人性化的显示…

linux用户基本操作

用户的管理 1.创建一个新用户user1 ,设置其主目录为/home/use1 useradd user1 -d /home/user12.查看/etc/passwd文件的最后一行&#xff0c;看看如何记录 vim /etc/passwd3.查看文件/etc/shadow文件的最后一行 vim /etc/shadow4.给用户设置密码 passwd user1 123456//密码…

linux课程--实验一 Linux 基本命令操作1

一、实验目的&#xff1a; (1)掌握Linux各类命令的使用方法。 (2)熟悉Linux字符界面操作环境。 二、实验准备 (1)了解Linux命令行的基本概念。 (2)自己建立目录结构以及目录下的文件。 三、实验过程&#xff08;内容包括&#xff1a;&#xff08;1&#xff09;练习linux命…

操作系统实验一 Linux基本操作|实验二 进程管理

由于当时没存代码&#xff0c;只有实验文档代码截图&#xff0c;文末也可直接获取实验文档。 操作系统实验 目录 实验一 Linux基本操作实验二进程管理 实验一 Linux基本操作 1实验目的 1.熟悉在Linux操作系统下的基本操作&#xff0c;对Linux操作系统有一个感性认识。 2.学…

Linux系统介绍及熟悉Linux基础操作

一、什么是Liunx Linux&#xff0c;全称GNU/Linux&#xff0c;是一种免费使用和自由传播的类UNIX操作系统&#xff0c;其内核由林纳斯本纳第克特托瓦兹&#xff08;Linus Benedict Torvalds&#xff09;于1991年10月5日首次发布&#xff0c;它主要受到Minix和Unix思想的启发&am…

操作系统——实验一(Linux基本操作)

操作系统——实验一(Linux基本操作) &#xff08;1&#xff09;练习Linux的基本安装和配置&#xff1b; &#xff08;2&#xff09;以root用户身份登陆&#xff0c;并使用“ls”,“cat”“cd”等常用命令来实现基本的文件操作并观察Linux文件系统的特点&#xff1b; &#xff…

Linux系统基础操作命令

目录 一、基本使用 1.编辑Linux命令行的辅助操作 2.常用的基础命令 1.切换用户&#xff08;su&#xff09; 2.pwd 查看当前工作目录 3.cd 切换工作目录 4.cp 复制 5.mkdir 创建目录 6.touch 创建文件 7.创建链接文件ln&#xff08;软链接、硬链接&#xff09; 8.alia…

Linux的基本操作

Linux的基本操作 文章目录 Linux的基本操作cd命令ls命令pwd命令touch命令cat命令mkdir命令rm命令cp命令mv命令man命令less命令head命令tail 命令date命令grep命令ps命令netstat命令 cd命令 语法&#xff1a;cd 目录名 功能&#xff1a;改变当前所在目录&#xff0c;将当前工作…

Linux基本操作之vi编辑器

Linux基本操作之vi编辑器 一、Vi编辑器的启动和退出启动退出 二、Vi编辑器的工作模式编辑模式插入模式命令模式 三、Vi编辑器的基本命令文件相关命令字符串搜索、替换和删除文本的复制、删除和移动 四、C/C编辑器gcc的使用1.编写代码2.使用命令编译和运行 一、Vi编辑器的启动和…

LINUX的基本操作学习总结

前言 从2020年11月定下了以后所打算从事的方向开始&#xff0c;就开始学习LINUX基础和LINUX环境编程&#xff0c;故谨以此文来记录LINUX的基础操作 声明&#xff1a;因个人能力有限&#xff0c;本文仅是个人的学习记录笔记&#xff0c;有错误之处还望指出 目录 1.LINUX的基础…

Linux基本操作之重定向文件

文章目录 RedirectionAppending to a fileRedirecting the Input通配符“*”和“?”文件名约定操作 Redirection 上一节 cat 命令的功能是将文件或标准输入组合输出到标准输出。这个命令常用来显示文件内容&#xff0c;或者将几个文件连接起来显示&#xff0c;或者从标准输入…

实验一 Linux基本操作

实验一 Linux基本操作 1&#xff0e; 实验要求 &#xff08;1&#xff09;掌握启动和退出Linux 操作系统方法&#xff1b; &#xff08;2&#xff09;了解与熟悉Linux 操作系统常用的Shell命令使用&#xff1b; &#xff08;3&#xff09;掌握Linux 操作系统下C程序的编辑、编译…

Linux介绍及基本操作

嵌入式之路&#xff0c;贵在日常点滴 ---阿杰在线送代码 目录 一、Linux简介 二、Linux介绍 三、Linux特点 四、常用命令 命令口终端 窗口分屏率 ​编辑配置串口大小 字体大小 ​编辑清屏 VI的使用 建立文件 模式 ​编辑编译文件 ​编辑运行编译文件 常用指令 …