思考与理解:
1,缺点:递归实现, 从某种意义上来说是简单问题复杂化,比起动态规划时间复杂度较高。
2,优点:它对我们理解栈的作用, 时间、空间复杂度等有重要意义。
学习目标:理解并熟练掌握递归算法,并将递归与栈结合做出汉诺塔习题。
学习任务:
代码说明:
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 <stdio.h>
/**
* @brief 递归加法。
*
* @param paraN
*
* @return 和
*/
int addTo(int paraN) {
int tempSum;
printf("进入addTo(%d)\n", paraN);
if (paraN <= 0) {
printf(" return 0\n");
return 0;
} else {
tempSum = addTo(paraN - 1) + paraN;
printf(" return %d\n", tempSum);
return tempSum;
}
}
/**
* 递归累加测试类
*/
void addToTest() {
int n, sum;
printf("---- addToTest开始测试 ----\n");
n = 5;
sum = addTo(n);
printf("0 +...+ %d = %d.\n\n", n, sum);
n = 1;
sum = addTo(n);
printf("0 +...+ %d = %d.\n\n", n, sum);
n = -1;
sum = addTo(n);
printf("0 +...+ %d = %d.\n\n", 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全部代码
#include <stdio.h>
/**
* @brief 汉诺塔移动递归函数
*
* @param paraDestination
* @param paraN
* @param paraSource
* @param paraTransit
*/
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);
}
}
/**
* @brief 测试类
*/
void hanoiTest() {
printf("---- addToTest 开始 ----\n");
int N;
printf("请输入加入的盘子数:");
scanf("%d",&N);
printf("%d个盘子的移动过程:\n",N);
hanoi(N, 'A', 'B', 'C');
printf("共移动%d次\n\n",cnt);
printf("---- addToTest 结束 ----");
}
int main(){
hanoiTest();
return 0;
}
1.2测试结果
移动两个
---- 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(子问题,递归)。