C语言递归实现汉诺塔问题

许多问题的求解过程都可以用递归分解方法描述,一个典型的例子是著名的汉诺(hanoi)塔问题。

1. 问题介绍

n 阶汉诺塔问题:假设有三个分别命名为 X、Y 和 Z 的塔座,再塔座 X 上有 n 个不同直径、编号为 1,2,...,n 的圆盘。现要求将塔座X上的 n 个圆盘移至塔座 Z 上,并仍按同样顺序叠排。

圆盘移动时必须遵循以下规则:

① 每次只能移动一个圆盘。

② 圆盘可以在 X、Y 和 Z 中的任何一个塔座上。

③ 任何时刻都不能将一个较大的圆盘压在较小的圆盘之上。

【算法思想】

① 当 n=1 时,问题比较简单,只要将编号为 1 的圆盘从塔座 X 直接移动到塔座 Z 上即可;

② 当 n>1 时,需要用塔座 Y 做辅助塔座,若能设法将压在编号为 n 的圆盘上的 n-1 个圆盘从塔座 X(依照上述原则)移至塔座 Y 上,则可先将编号为 n 的圆盘从塔座 X 移至塔座 Z上,然后再将塔座 Y 上的 n-1 个圆盘(依照上述原则)移至塔座 Z 上。

2. 代码实现

下面是使用 C 语言实现汉诺塔问题的代码,同时统计总共移动了多少次。

c 复制代码
#include<stdio.h>

int count = 0;

void hanoi(int n, char from, char aux, char to) {
	if (n == 1) {
		printf("No.1 from %c to %c\n", from, to);
		count++;
		return;
	}

	hanoi(n - 1, from, to, aux);

	printf("No.%d from %c to %c\n", n, from, to);
	count++;

	hanoi(n - 1, aux, from, to);
}

int main() {
	int n = 0;
	scanf("%d", &n);
	hanoi(n, 'A', 'B', 'C');
	printf("%d\n", count);
	return 0;
}

第一步:移动上面 n-1 个盘子。

第二步:移动第 n 个盘子,即最大盘子。

第三步:再移动上面 n-1 个盘子。

3. 代码思路

c 复制代码
void hanoi(int n, char from, char aux, char to)
c 复制代码
hanoi(n, 'A', 'B', 'C');

把 n 个盘子从 A 柱子借助 B 柱子移动到 C 柱子。

4. 递归终止条件

c 复制代码
if (n == 1) {
    printf("No.1 from %c to %c\n", from, to);
    count++;
    return;
}

当只有一个盘子时,不需要再继续分解问题,直接把这个盘子从起始柱子移动到目标柱子即可。

这里的 return 非常重要。它表示当前函数执行结束,不再继续向下执行。如果没有这个 return,程序会继续调用:

c 复制代码
hanoi(n - 1, from, to, aux);

5. 代码分析

在汉诺塔问题中,每输出一次:

c 复制代码
printf("No.%d from %c to %c\n", n, from, to);

就表示真实移动了一次盘子。所以每打印一次移动步骤,就应该让移动次数加一:

c 复制代码
count++;

递归调用本身不是一次移动,而是"一组移动过程"。

6 汉诺塔的执行过程

总结

汉诺塔问题虽然代码不长,但非常适合理解递归中的三个关键点:递归函数的含义、递归终止条件,以及递归问题如何分解为更小规模的问题。

相关推荐
Scott9999HH1 小时前
【IIoT流量实战】蒸汽管道阀门全关却仍有流量?用 Python 实现涡街信号 FFT 频谱分析与温压全补偿积算网关,深度拆解靠谱的涡街流量计厂家硬核技术标准
开发语言·python
码智社2 小时前
AES加密原理详解及Java实现加解密实战
java·开发语言
AI云海2 小时前
python 列表、元组、集合和字典
开发语言·python
萧瑟余晖3 小时前
JDK 26 新特性详解
java·开发语言
马优晨3 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
人邮异步社区5 小时前
怎么把C语言学到精通?
c语言·开发语言
心平气和量大福大6 小时前
C#-WPF-控件-TextBox 数据绑定
开发语言·c#·wpf
ttwuai6 小时前
Cursor 生成 CRUD 后,Go 后台接口别只测 200:JWT、RBAC 和 tenant_id 怎么验
开发语言·后端·golang
এ慕ོ冬℘゜6 小时前
前端基础:什么是时间戳?JS获取时间戳三种方法与实战用途
开发语言·前端·javascript
执明wa6 小时前
LayoutInflater详解: XML是如何变成View的?
android·xml·开发语言·android studio