数据结构 C 代码 3.4.5: 递归(累加&汉诺塔)

 思考与理解:

1,缺点:递归实现, 从某种意义上来说是简单问题复杂化,比起动态规划时间复杂度较高。

2,优点:它对我们理解栈的作用, 时间、空间复杂度等有重要意义。

学习目标:理解并熟练掌握递归算法,并将递归与栈结合做出汉诺塔习题。

学习指导:帆神代码累加 汉诺塔

学习任务:

  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 <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(子问题,递归)。

  

  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值