C语言:递归入门 汉诺塔问题

本文详细介绍了递归的概念,包括尾递归和非尾递归,并通过阶乘函数和汉诺塔问题实例解析递归的运用。递归在解决某些数学问题和数据结构操作中尤为有效,但也存在内存消耗大和效率低的缺点。理解递归的关键在于找到递归公式和递归出口。同时,文章提供了汉诺塔问题的递归和非递归解决方案,帮助读者深入理解递归思想。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

递归是什么?

在定义一个过程或函数时,出现调用本过程或本函数的成分称为递归
如果一个递归过程或函数中的递归调用语句是最后一条执行语句,则称这种递归调用为尾递归

例如:计算阶乘函数

int f(int n){
    if(n==0){
        return 1;
    } else return (f(n-1)*n);
}

递归解决问题应满足三个条件

  1. 需要解决的问题可以转化为一个或多个子问题求解,而这些子问题的求解方法与原问题相同,只是数量规模上不同
  2. 递归调用次数必须是有限
  3. 必须要结束条件终止递归

递归优点:结构简单、清晰、方便证明准确性
递归缺点:占用内存多,执行效率低、不容易优化

什么时候使用递归?

  1. 定义是递归的:许多数学公式、定义是递归时。例:阶乘、Fibonacci数列等
  2. 数据结构是递归的:例:单链表、树等
typedef struct LNode{
    ElemType data;
    struct LNode *next;
}LinkNode;
//结构体LNode的声明用到了它本身

//利用递归方式求单链表所有data域的和
int sum(LinkNode *L){
    if(L==NULL){
        return 0;
    } else return (L->data+sum(L->next));
}
  1. 问题的求解方式是递归的:Hanoi问题
    n=4
    汉诺塔问题的规则在此不再赘述
    设Hanoi(n,x,y,z)表示将n个盘片从x轴,经由y轴,移动到z轴
    我们可以将其拆分为三步进行(找到递归公式)

第一步:将x轴上 n-1 个盘片经由 z轴 移动到 y轴
第二步:将x轴上最后一个盘片直接移动到 z轴
第三步:将y轴上 n-1 个盘片经由 x轴 移动到 z轴

那么问题是:我们如何完成第一步和第三步呢?
其实第一步和第三步又可以分别拆分为上述三个步骤(递归公式)

递归出口:当只有一个盘片时,可以将它直接移动。
代码实现

#include <stdio.h>
//汉诺塔
void hanoi(int n,char A,char B,char C){
	if(n==1){
		printf("%c -> %c\n",A,C);
	} else{
		hanoi(n-1,A,C,B);
		printf("%c -> %c\n",A,C);
		hanoi(n-1,B,A,C);
	}
} 

int main(){
	hanoi(3,'A','B','C');
	return 0;
}


emmm,我的语言表达能力更进一步描述清楚
你可以手动执行一次函数,一定要注意形参和实参,通过一个栈模拟,便可以理解了!

这里推荐几个B站up主,我也是看他们的视频才理解的,
首先了解汉诺塔问题可以看李永乐老师
然后看“正月点灯笼”的递归入门视频
最后整个函数的执行步骤可以看“懒猫老师”的视频。

顺便贴一下汉诺塔问题的非递归写法
在这里插入图片描述

总结:在面对递归问题时,找到递归公式,递归出口是关键

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值