数据结构学习笔记之递归+汉诺塔

定义:
            一个函数自己直接或间接调用自己

当在一个函数的运行期间调用另一个函数时,在运行被调函数之前,系统需要完成三件事:
1、将所有的实际参数,返回地址等信息传递给被调函数保存
2、为被调函数的局部变量(包括形参)分配存储空间
3、将控制转移到被调函数的入口

从被调函数返回主调函数之前,系统也要完成三件事:
1、保存被调函数的返回结果
2、释放被调函数所占的存储空间
3、依照被调函数保存返回地址将控制转移到调用函数

多个函数被调用的时候,按照“后调用先返回”的原则,上述函数之间信息传递和控制转移必须借助“栈”来实现,即系统将整个程序运行时所需的数据空间安排在一个栈中,每当调用一个函数时,就在栈顶分配一个存储区,进行压栈操作,每当一个函数退出时,就释放它的存储区,进行出栈操作,当前运行的函数永远都在栈顶位置

A函数调用A函数和A函数调用B函数在计算机看来是没有任何区别的,只不过用我们日常的思维方式理解比较怪异而已

递归必须满足的三个条件:
1、递归必须有一个明确的终止条件
2、该函数所处理的数据规模必须在递减
3、这个转化必须是可解的

循环和递归:
        递归:
                易于理解
                速度慢
                存储空间大
        循环
                不易理解
                速度快
                存储空间小

递归调用的应用:
        树和森林就是以递归的方式定义的
        树和图的很多算法都是以递归来实现的
        很多数学公式就是以递归方式来实现的
                斐波那契序列:
                1 1 2 3 5 8 13 21 34.....

利用递归求阶乘
#include <stdio.h>
#include <stdlib.h>

long mul(long n)
{
 if (1 == n)
  return 1;
 else
  return n * mul(n - 1);
}

int main(void)
{
 long val, i;
 printf("请输入一个数字i = ");
 scanf_s("%d", &i);
 val = mul(i);

 printf("阶乘为%d \n", val);

 system("pause");
 return 0;
}

汉诺塔的实现
伪算法:
if(n > 1)
{
    先把A柱子上的前n-1个盘子从A借助C移到B
    将A柱子上的第n个盘子直接移到C
    再将B柱子上的n-1个盘子借助A移到C

如果只有 1 个盘子,则不需要利用B塔,直接将盘子从A移动到C。
如果有 2 个盘子,可以先将盘子1上的盘子2移动到B;将盘子1移动到C;将盘子2移动到C。这说明了:可以借助B将2个盘子从A移动到C,当然,也可以借助C将2个盘子从A移动到B。
如果有3个盘子,那么根据2个盘子的结论,可以借助c将盘子1上的两个盘子从A移动到B;将盘子1从A移动到C,A变成空座;借助A座,将B上的两个盘子移动到C。
  以此类推,上述的思路可以一直扩展到 n 个盘子的情况,将将较小的 n-1个盘子看做一个整体,也就是我们要求的子问题,以借助B塔为例,可以借助空塔B将盘子A上面的 n-1 个盘子从A移动到B;将A最大的盘子移动到C,A变成空塔;借助空塔A,将B塔上的 n-2 个盘子移动到A,将C最大的盘子移动到C,B变成空塔…
  根据以上的分析,不难写出程序:


#include <stdio.h>
#include <stdlib.h>

void hannuota(int n, char A, char B, char C)
{
	/*如果是一个盘子,直接将A柱子上的盘子移到C
		否则 先将A柱子上的n-1个盘子借助C移到B
		直接将A柱子上的盘子从A移到C
		最后将B柱子上的n-1个盘子借助A移到C*/

	if (1 == n)
		printf_s("将编号为%d的盘子直接从%c柱子移到%c柱子\n", n, A, C);
	else
	{
		hannuota(n - 1, A, C, B);
		printf_s("将编号为%d的盘子直接从%c柱子移到%c柱子\n", n, A, C);
		hannuota(n - 1, B, A, C);
	}
}

int main(void)
{
	char ch1 = 'A';
	char ch2 = 'B';
	char ch3 = 'C';
	int n;

	printf_s("请输入要移动盘子的个数:");
	scanf_s("%d", &n);

	hannuota(n, 'A', 'B', 'C');

	system("pause");
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值