c语言函数之递归函数的认识.docVIP

  1. 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
  2. 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  3. 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
  4. 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
  5. 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们
  6. 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
  7. 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
c语言函数之递归函数 朱有鹏 1、递归函数 1.1、函数的调用机制 C语言函数的调用一般在X86平台是用栈的方式来支持其操作的(也就是Calling Convention),栈是先进后出的数据结构,当函数发生调用的时候,函数以入栈的方式,将函数的返回地址、参数等进行压栈,C语言默认环境下的调用规范为,参数是从右向左依次压栈(如:printf函数),这就是函数的调用机制。同时函数每调用一次,就会进行一次压栈,其所占的空间彼此独立,调用函数和被调用函数依靠传入参数和返回值彼此联系。 如: 一个main()函数调用函数sub(int a, int b)的简单的内存图形是: int a Int b sub()返回地址 main参数 main()返回地址 1.2、递归函数 (1)什么是递归函数? 通过简单的了解函数的调用机制,在程序设计中经常会用递归函数解决问题,此方法清晰易于理解。那么什么是递归函数呢?递归函数的本质就是函数直接或间接调用其函数本身。 直接调用函数调用本身示例:求n的阶乘? factorial()函数直接调用其本身。 间接调用是函数调用其它函数,其它函数又调用其本身函数示例: func_1()函数中调用了func_2() 函数,func_2()函数又调用了func_1() 这样的方式就是间接递归,此示例,本身就是个错误,各位不要急后面一一道来(没有注意收敛性)。 递归的调用的原理 比如下例: #includestdio.h void recursion(int n) { printf(递归前:n = %d.\n, n); if (n 1) { recursion(n-1); } else { printf(结束递归,n = %d.\n, n); } printf(递归后:n = %d.\n, n); } int main(void) { void recursion(3); } 执行结果为: 递归前:n = 3. 递归前:n = 2. 递归前:n = 1. 结束递归,n = 1. 递归后:n = 1. 递归后:n = 2. 递归后:n = 3. 函数的执行顺序,如图所示: 解析: 当程序执行时,通过主函数执行到void recursion(3);时,以n=3进入recursion函数中。 第一次进入recursion函数时n=3,执行图中编号为①的输出语句,“递归前:n = 3.”判断满足 n1 的条件,继续执行if条件下的语句“recursion(n-1);”此时以recursion(2)第二次调用recursion 函数。 第二次进入recursion函数n=2,执行图中编号为②的输出语句,“递归前:n = 2.”判断满足n1 的条件,继续执行if条件下的语句“recursion(n-1);”此时以recursion(1)第三次调用recursion函 数。 第三次进入recursion函数时,n=1,再一次执行图中编号为③输出语句,“递归前:n = 1.”然 后进行判断,由于不满足条件,执行else,因此输出图中编号为④的输出语句,“结束递归,n = 1”, 然后顺序执行函数,执行该函数的最后一句,图中编号为⑤输出语句“结束递归,n = 1.”。然 后该函数返回第二次调用时。 第二次调用时,继续顺序执行,输出图中编号为⑥输出语句,输出“递归后:n = 2.”。然后该 函数返回第一次调用时。 第一次调用时,继续顺序执行,输出图中编号为⑦输出语句,输出“递归后:n = 1.”.整个递归 完成。 刚刚我们说过函数的调用就是用栈来做支持的,递归函数只是函数调用的一种方式,每调用一次就会进行一次压栈,就会消耗调一定的栈内存空间。栈内存大小是一定的,因此也限制了递归深度。 1.3、使用递归的原则:收敛性、栈溢出 收敛性 从字面意思理解,收敛性就是总会有个值来约束着,就是收敛。递归函数必须有一个终止递归的条件作为约束。当每次这个函数被执行时,判断此条件后,决定是否继续执行递归,这个执行约束条件必须能够被满足。如果没有递归终止条件,则这个递归没有收敛性,这个递归最终要失败。 (2)栈溢出 递归调用是占用栈内存的,每次递归调用都会消耗一定的栈空间。因此必须在栈内存耗尽之前结束递归,否则就会栈溢出,栈溢出后会导致整个程序崩溃。 进行递归函数设计时,一定要重点注意收敛性和栈溢出的问题,一般有有两种不好的情况,第一种就是没有判断递归的结束的约束值,递归会不停的执行下去,直到内存空间被用完并导致程

文档评论(0)

xuefei111 + 关注
实名认证
文档贡献者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档