思考与理解:
1,缺点:递归实现, 从某种意义上来说是简单问题复杂化,比起动态规划时间复杂度较高。
2,优点:它对我们理解栈的作用, 时间、空间复杂度等有重要意义。
学习目标:理解并熟练掌握递归算法,并将递归与栈结合做出汉诺塔习题。
学习指导:帆神代码累加 汉诺塔
学习任务:
- 抄写代码
学习成果目录
1数据结构 C 代码 3.4: 累加的递归实现
1.1全部代码
1.2测试结果
2数据结构 C 代码 3.5: 汉诺塔问题
1.1全部代码
1.2测试结果
1.3附图与理解
代码说明:
1累加
1.1这是最简单的递归程序, 没有之一.
1.2系统会自动为递归程序建栈, 栈里面存放的是函数及相应数据 (局部变量等).
1.3这种累加的时间复杂度与 for 循环的一致, 均为O(n)O(n)O(n), 但空间复杂度为O(n)1.4O(n)O(n), 比 for 循环的 O ( 1 ) O(1)O(1) 高. 使用的栈空间.
1.5clearAddTo 是清晰版, 没有调试语句.2汉诺塔
2.1累加的递归实现, 纯粹是为了本程序打基础.
2.2汉诺塔问题很简单, 函数满打满算只有 9 行; 汉诺塔问题很困难, 不把几个参数搞清楚, 直接在里面绕晕.
2.3从这里可以看到使用有意义的, 长变量名的优势: 程序可读性获得大幅提升.
2.4初始条件是 0 个盘子, 这样对于负数个盘子的判断就比较方便.
2.5算法的时间复杂度是O(2n)O(2^n)O(2n), 空间复杂度是O(n)O(n)O(n). 都需要画图来解释.
学习时间:
2022.5.12
1数据结构 C 代码 3.4: 累加的递归实现
1.1全部代码
#include
int addTo(int paraN) {
int tempSum;
printf("进入addTo(%d)n", paraN);
if (paraN <= 0) {
printf(" return 0n");
return 0;
} else {
tempSum = addTo(paraN - 1) + paraN;
printf(" return %dn", tempSum);
return tempSum;
}
}
void addToTest() {
int n, sum;
printf("---- addToTest开始测试 ----n");
n = 5;
sum = addTo(n);
printf("0 +...+ %d = %d.nn", n, sum);
n = 1;
sum = addTo(n);
printf("0 +...+ %d = %d.nn", n, sum);
n = -1;
sum = addTo(n);
printf("0 +...+ %d = %d.nn", n, sum);
printf("---- addToTest结束测试 ----n");
}
int main() {
addToTest();
return 0;
}
1.2测试结果
---- addToTest开始测试 ----
进入addTo(5)
进入addTo(4)
进入addTo(3)
进入addTo(2)
进入addTo(1)
进入addTo(0)
return 0
return 1
return 3
return 6
return 10
return 15
0 +...+ 5 = 15.
进入addTo(1)
进入addTo(0)
return 0
return 1
0 +...+ 1 = 1.
进入addTo(-1)
return 0
0 +...+ -1 = 0.
---- addToTest结束测试 ----
--------------------------------
Process exited after 0.03249 seconds with return value 0
Press ANY key to continue...
2数据结构 C 代码 3.5: 汉诺塔问题
1.1全部代码
#includeint addTo(int paraN) { int tempSum; printf("进入addTo(%d)n", paraN); if (paraN <= 0) { printf(" return 0n"); return 0; } else { tempSum = addTo(paraN - 1) + paraN; printf(" return %dn", tempSum); return tempSum; } } void addToTest() { int n, sum; printf("---- addToTest开始测试 ----n"); n = 5; sum = addTo(n); printf("0 +...+ %d = %d.nn", n, sum); n = 1; sum = addTo(n); printf("0 +...+ %d = %d.nn", n, sum); n = -1; sum = addTo(n); printf("0 +...+ %d = %d.nn", n, sum); printf("---- addToTest结束测试 ----n"); } int main() { addToTest(); return 0; }
1.2测试结果
---- addToTest开始测试 ----
进入addTo(5)
进入addTo(4)
进入addTo(3)
进入addTo(2)
进入addTo(1)
进入addTo(0)
return 0
return 1
return 3
return 6
return 10
return 15
0 +...+ 5 = 15.
进入addTo(1)
进入addTo(0)
return 0
return 1
0 +...+ 1 = 1.
进入addTo(-1)
return 0
0 +...+ -1 = 0.
---- addToTest结束测试 ----
--------------------------------
Process exited after 0.03249 seconds with return value 0
Press ANY key to continue...
2数据结构 C 代码 3.5: 汉诺塔问题
#include1.2测试结果int cnt=0; void hanoi(int paraN, char paraSource, char paraDestination, char paraTransit) { if (paraN <= 0) { return; } else { cnt++; hanoi(paraN - 1, paraSource, paraTransit, paraDestination); printf(" %c -> %c n", paraSource, paraDestination); hanoi(paraN - 1, paraTransit, paraDestination, paraSource); } } void hanoiTest() { printf("---- addToTest 开始 ----n"); int N; printf("请输入加入的盘子数:"); scanf("%d",&N); printf("%d个盘子的移动过程:n",N); hanoi(N, 'A', 'B', 'C'); printf("共移动%d次nn",cnt); printf("---- addToTest 结束 ----"); } int main(){ hanoiTest(); return 0; }
移动两个
---- addToTest 开始 ---- 请输入加入的盘子数:2 2个盘子的移动过程: A -> C A -> B C -> B 共移动3次 ---- addToTest 结束 ----
移动三个
---- addToTest 开始 ---- 请输入加入的盘子数:3 3个盘子的移动过程: A -> B A -> C B -> C A -> B C -> A C -> B A -> B 共移动7次 ---- addToTest 结束 ----
1.3附图与理解
- n = 1 时,
- 直接把盘子从 A 移到 C;
- n > 1 时,
- 先把上面 n - 1 个盘子从 A 移到 B(子问题,递归);
- 再将最大的盘子从 A 移到 C;
-
再将 B 上 n - 1 个盘子从 B 移到 C(子问题,递归)。
- n = 1 时,
- 直接把盘子从 A 移到 C;
- n > 1 时,
- 先把上面 n - 1 个盘子从 A 移到 B(子问题,递归);
- 再将最大的盘子从 A 移到 C;
-
再将 B 上 n - 1 个盘子从 B 移到 C(子问题,递归)。



