Day05 从汉诺塔Hanoi看递归函数调用

函数调用有很多的知识点,但在我看来递归函数的书写算得上函数调用里边的重难点,因此进行梳理。

函数递归分为直接递归与间接递归,就是函数直接过间接的嵌套调用自身。递归这个概念可以分解来看:递即“递推”,是将大问题分级为小问题向前递进,推进以获得更小规模的简单问题进行解决,包含了终止条件的最小规模;归即“回归”是自最小规模终止条件成立时对本质问题的回溯,重构大问题的本来面目。常见递归算法的基本格式如下:

Typename func(int count,...){

//终止条件

if(count)

return value;

else

return func(count-1,...);//递归调用

}

一共包含两个主要条件:终止条件与递归调用。

递归的适用场景为一个大问题可以拆解为同等类型,但规模更小的问题且最小问题解决简便明确的场景,如阶乘,菲波那切数列。今天我要介绍著名的汉诺塔问题的递归算法,但是在此之前还是贴一段阶乘的代码,让大家对递归有一定认识。

求阶乘:

 以上代码自行阅读,了解简单的递归调用逻辑。现在开始回顾汉诺塔问题:
汉诺塔(Tower of Hanoi),又称河内塔,是一个源于印度古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。

分析问题:

 

我们先对问题进行简要的概括:n层汉诺塔经A由B到C!

终止条件:就是只剩一个圆盘(最小圆盘)需要移动,则直接移动到C上;

递归分解步骤:

Step1:n-1层汉诺塔经A由C到B;//子问题

Step2:最大圆盘移动到C;

Step3:n-1层汉诺塔经B由A到C;//子问题

分析以上步骤不难看出处线路两次子问题的求解,现给出如下代码:

#include<iostream>
using namespace std;
void move(char x, char y) {
	static int n = 1;
	printf("%d) %c-->%c\n", n, x, y);
	n++;
}

void hanno(int n, char A, char B, char C) {
	if (n == 1) {
		move(A, C);//终止条件
	}
	else {
		hanno(n - 1, A, C, B);//Step1
		move(A, C);//Step2
		hanno(n - 1, B, A, C);//Step3
	}
}
int main() {
	int level = 0;
	cout << "输入汉诺塔层数:";
	cin >> level;
	hanno(level, 'a', 'b', 'c');
	cin.get();
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44212242/article/details/125658862