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 汉诺塔的执行过程

总结

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

相关推荐
不吃土豆的马铃薯4 小时前
Spdlog 入门:日志记录器与日志槽基础详解
服务器·开发语言·c++·c·日志·spdlog
凯瑟琳.奥古斯特4 小时前
传输层核心功能解析
开发语言·网络·职场和发展
Fuyo_11194 小时前
C++中的活字印刷术——模板·初阶
开发语言·c++·笔记
在角落发呆4 小时前
跨越网络鸿沟:传统文件传输与现代内网穿透的奇妙交响
开发语言·php
Season4504 小时前
C++之模板元编程(前置知识 constexpr)
开发语言·c++
AI玫瑰助手4 小时前
Python运算符:比较运算符(等于不等等于大于小于)与返回值
android·开发语言·python
计算机安禾5 小时前
【c++面向对象编程】第40篇:单例模式(Singleton)的多种C++实现
开发语言·c++·单例模式
LuminousCPP5 小时前
数据结构 - 线性表第三篇:基于顺序表实现 C 语言通讯录(基础功能篇)
c语言·数据结构·经验分享·笔记·算法
_日拱一卒5 小时前
LeetCode:114二叉树展开为链表
java·开发语言·算法