代码:
#include <stdio.h>
/**
* Hanoi.
*/
void hanoi(int paraN, char paraSource, char paraDestination, char paraTransit) {
if (paraN <= 0) {
return;
} else {
hanoi(paraN - 1, paraSource, paraTransit, paraDestination);
printf("%c -> %c \r\n", paraSource, paraDestination);
hanoi(paraN - 1, paraTransit, paraDestination, paraSource);
}// Of if
}// Of hanoi
/**
* Test the hanoi function.
*/
void hanoiTest() {
printf("---- addToTest begins. ----\r\n");
printf("2 plates\r\n");
hanoi(2, 'A', 'B', 'C');
printf("3 plates\r\n");
hanoi(3, 'A', 'B', 'C');
printf("---- addToTest ends. ----\r\n");
}// Of addToTest
/**
The entrance.
*/
void main() {
hanoiTest();
}// Of main
运行结果:
汉诺塔(Tower of Hanoi),又称河内塔,是一个源于印度古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
如果考虑一下把64片金片,由一根针上移到另一根针上,并且始终保持上小下大的顺序。这需要多少次移动呢?这里需要递归的方法。假设有n片,移动次数是f(n).显然f(1)=1,f(2)=3,f(3)=7,且f(k+1)=2*f(k)+1。此后不难证明f(n)=2^n-1。
关于该代码的分析:
1.自顶向下,逐渐求精,函数调用:
自顶向下就是把整个大的问题逐步拆分成几个小问题,从最开始的条件分析,以汉诺塔为例,整个求次数可以划分成三步:
先把n-1个圆盘移到一个柱子上,然后把底盘移到C柱上,最后把n-1个圆盘移动到C柱上。这就是解决问题的元步骤,通过函数三步的调用就能算出最终的结果。
2.递归与分治
每次都是在n个盘子的移动中调用n-1个盘子移动的函数,然后制定一个下界,之后就是函数自己调用一步步从n走到0,最后给出我们想要的结果。
3.不要跨层分析
简单的来说就是我们发现他总的规律,就不用想他具体要怎么执行,系统会自动帮你把后面的步骤做完。
4.形参与实参
形参指的是函数中参数列表里的那几个元素,而实参是调用函数时,赋值给形参的原来的参数,也就是说调用函数的时候把实参的值赋值给形参,这两个参数不公用同一地址。
5.有意义、规范的标识符
标识符为了让你过几个月还能一眼就看懂什么意思,给变量一个明确意义的名字,增强程序的可读性。
6.时间复杂度
T(n)=2*T(n-1)+1;最后得出Tn=2^n;
7.递归栈
每次编译器读到函数的时候就会把这个函数push进栈,然后执行完之后才会pop出栈,所以如果在一个函数内部读到另一个函数就会先让另一个函数入栈,出栈,做完才轮到外面那一层函数。
8.空间复杂度
根据上面递归栈的代码跟踪,我们会发现每次最多递归层数不会超过N层,也就是栈内使用到的空间最多只有N个空间。所以空间复杂度为O(n)。