Hanoi问题
代码:
#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);
}
}
/**
*Test the hanoi fiction,
*/
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");
}
/**
The entrance.
*/
int main() {
hanoiTest();
}
运行结果:
---- addToTest begins. ----
2 plates
A -> C
A -> B
C -> B
3 plates
A -> B
A -> C
B -> C
A -> B
C -> A
C -> B
A -> B
---- addToTest ends. ----
给定三根柱子,记为 A,B,C,其中 A柱子上有 n个盘子,从上到下编号为 0到 n-1 ,且上面的盘子一定比下面的盘子小。移动时应注意:一次只能移动一个盘子,大的盘子不能压在小盘子上。
本题利用递归与分治的思想,将原问题分解为若干个规模较小与原问题形式相同的子问题,再将各个子问题的解合并为原问题的解。
简单分为三个步骤:
(1) 把n-1个盘子由A 移到 B;
(2) 把第n个盘子由 A移到 C;
(3) 把n-1个盘子由B 移到 C;
1、自顶向下,逐渐求精,函数调用
解决一个问题时,先从大的方向考虑,而不想具体的解决方法。将办法大致分成几个步骤,构建解决问题的框架,再填充内容,逐渐求精。
2、递归与分治(基础与归纳)
解决汉诺塔问题的思想,将大问题分解成规模较小的形式相同的子问题。对于一个规模为n的问题,若该问题可以容易的解决(比如规模n较小)则直接解决,否则将其分解为k个规模较小的子问题,这些子问题互相独立且与原问题形式相同,递归地解决这些子问题,然后将各个子问题的解合并得到原问题的解。
3、不要跨层分析
以汉诺塔问题为例,对于要挪动n个盘子的问题,下一步应分析挪动n-1个盘子而不要跨层去考虑挪动n - 2个盘子的事情。
4、形参与实参(代码跟踪)
形参相当于名字而实参是具体的数值。形参变量只有在函数被调用时才会分配内存,调用结束后,立刻释放内存,所以形参变量只有在函数内部有效,不能在函数外部使用。 实参可以是常量、变量、表达式、函数等,无论实参是何种类型的数据,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参,所以应该提前用赋值、输入等办法使实参获得确定值。
5、有意义、规范的标识符
有意义且规范的标识符,提高代码的可读性,可维护性。标识符是严格区分大小写的。标识符最好选择有意义的英文单词组成,不要使用拼音。标识符不能是C语言的关键字和保留标识符。操作系统和 C 语言标准库里的标识符一般以下划线开头。因此,我们应该避免使用下划线作为我们自己定义的标识符的开头。
6、时间复杂度
是指执行当前算法所消耗的时间,我们通常用时间复杂度来描述。算法执行时间需通过依据该算法编制的程序在计算机上运行时所消耗的时间来度量。一个算法执行所耗费的时间,从理论上是不能算出来的,必须上机运行测试才能知道。但我们不可能也没有必要对每个算法都上机测试,只需知道哪个算法花费的时间多,哪个算法花费的时间少就可以了。并且一个算法花费的时间与算法中语句的执行次数成正比例,哪个算法中语句执行次数多,它花费时间就多。一个算法中的语句执行次数称为语句频度或时间频度。记为T(n)。
7、递归栈(代码跟踪)。
整个递归过程,可以分为两个过程
递:也就是函数自己调用自己,不断的将变量值不断的以栈的的形式压入分配的空间中,期间要入栈中的值不能被访问。
归:符合结束条件,函数调用结束,然后变量值出栈,并释放变量原来占用的空间。
8、空间复杂度
类似于时间复杂度的讨论,一个算法的空间复杂度S(n)定义为该算法所耗费的存储空间,它也是问题规模n的函数。渐近空间复杂度也常常简称为空间复杂度。空间复杂度是对一个算法在运行过程中临时占用存储空间大小的一个量度,同样反映的是一个趋势,我们用 S(n) 来定义。空间复杂度比较常用的有:O(1)、O(n)、O(n²)。