推广 热搜: csgo  vue  angelababy  2023  gps  新车  htc  落地  app  p2p 

编程语言C语言的“递归函数”

   2023-08-15 网络整理佚名1780
核心提示:当然了,严格来说,C语言对“递归”也是做了一定的支持,至少递归函数就属于C语言的一种语法,这其实与C语言的基本设计思想有关:C语言从诞生至今,有一个特点是始终坚持的——尽可能的保持简洁,给程序员比较大的自由。函数的C语言代码本文还通过两个实例,从编程语言和实际应用两个角度讨论了如何分析C语言中的递归函数,可见,递归有时的确能够简洁的解决问题。

初学者在学习C语言的过程中,遇到“递归”的概念时,常常会感到困惑。 坦白讲,“递归”确实是编程语言中比较难理解的一个概念,而“递归”能解决的问题,一般的循环语句也能解决。 从某种程度上来说,C语言中的“递归”就相当于循环语句,那么为什么C语言不“抛弃”这种难以理解的“递归”呢?

为什么C语言不抛弃“递归”?

事实上,“递归”是否难以理解取决于程序员看待问题的角度。 应该明白,C语言程序是服务于人们现实生活的需要的。 在我看来,如果脱离实际问题,只从编程语言的角度看问题,“递归”确实很难理解。 相反,如果结合实际解决的问题,有时“递归”会更清晰易懂。 请看下面的C语言代码示例:

(intn){if(0==n);*(n-1);}

()函数是典型的递归函数。 虽然它的代码很简单,但是仅从编程语言的角度来理解这个函数确实很困难——当n!=0时,函数似乎永远在嵌套自己,虽然粗略的一步步分析可以得到输出函数的功能,一不小心就会出错。

现在从另一个角度考虑()函数,尝试分析一下这个函数需要解决的“实际需求”。 不难看出 () 函数实际上表示:

将这两句话转换成数学语言,即:

()函数的数学描述

如果n被限制为不小于0的整数,那么这显然就是数学中整数阶乘的定义,即(n)函数的输出是n!。 可见,递归函数()其实就是直接用C语言来“描述”n!的数学定义,所以从这个角度来看,“递归”似乎并没有那么难理解。

当然,也可以写一个程序来计算n! 在C语言中使用循环语句。 读者可以自己写一下,应该能发现循环语句计算n! 实施与设计思维的角度不同。

因此,从上面的例子可以看出,C语言中的“递归”并不是一种语法,而是一种“编程思维”,所以“丢弃”是无从谈起的。 当然,严格来说,C语言在一定程度上也支持“递归”。 至少递归函数属于C语言的语法。 这其实和C语言的基本设计思想有关:从C语言诞生以来,有一个特性是始终坚持的——尽可能保持简单,给予程序员更大的自由。 所以,既然“递归”思维是个好思维,C语言当然必须提供递归函数来支持。

让我们看另一个例子

为了加深对递归的理解,这里再举一个例子,请看下面的C语言代码:

#(,){if(左>=右);=(左+右)/2;(":%d%d%d\\n",左,中,右);测试(左,中); 测试(中+1,右);("之后:%d%d%d\\n",左,中,右);}(){测试(0,5);;}

test()函数的C语言代码

test()函数显然是一个递归函数,其代码也比较简单,但是内部递归调用了两次,稍微复杂一些。 接下来我们从编程语言和实际需求的角度来分析test()函数的功能。

首先,从编程语言的角度来看,很明显test()函数会被多次调用。 为了便于讨论,每次调用 test() 函数时,我们都会在函数名中添加后缀“_xx”。

第一次在main()函数中调用test()函数,进入test()函数后,程序会首先递归调用test(left, mid); 该行可以写为:

此时需要注意的是,执行“test(left, mid)”时会递归调用~3(),因此会返回“test(mid+1, right)”。

返回(0, 1)时,left=0,right=1,mid=0,所以test(mid+1, right)会直接返回,输出“after: 0 0 1”; 然后返回 (0, 2) ,同理,输出“after: 0 1 2”; 然后返回 (0, 5) test(mid+1, right); 线,此时left=0,right=5,mid=2,接下来的过程将进行如下:

此时需要注意的是,执行“test(mid+1, right)”时会递归调用test4~6(),因此它们会返回到“(”after:...”。

函数返回到(3, 4)后,left=3,right=4,mid=3,所以输出“after: 3 3 4”,而返回(3, 5),输出“after: 3 4 5”,返回(0, 5),输出“after: 0 2 5”。 整理一下,上述C语言程序的输出结果如下:

::::::::::025

可见,从编程语言的角度分析递归函数确实是一件比较困难的事情。 如果test(0, 105)函数输入的参数比较宽,基本上可以认为是不可分析的。 现在我们尝试从实际需求的角度来理解递归函数test()的作用,我们应该能够轻松得到以下信息:

稍微了解一下,应该就能明白test()函数的作用了:mid是left和right的中间值,所以test(left, mid)可以看成是二分后的左半部分,test( mid+1, right)可以看做二分后的右半部分,所以test()函数的作用就是不断对left~right区间进行二分,直到二分不能再继续(left>=right),这个过程是一步步递归的,所以test()函数也会一步步输出二进制结果。 以分析“after:...”输出为例,test(0, 5)会依次输出:

5025

这与从编程语言角度分析的结果是一致的。 明白了这一点之后,现在我们介绍一个应用示例,假设有一个数组{3,2,5,1,4},调用test(0,5)对数组进行逐步划分,过程应该如下所示下图:

二元群过程

至此,我们已经从实际需求的角度分析了递归函数。 可见,理解递归函数实际上就是理解它们的设计,从更高的角度理解它们的意义。

概括

“递归”并不是C语言中的语法,它更像是一种思想,所以“C语言为什么不抛弃“递归””是没有意义的。 本文还通过两个例子讨论了如何从编程语言和实际应用的角度来分析C语言中的递归函数。 可见,递归有时可以简洁地解决问题。 不过,我不得不承认,递归确实是一个很难理解的概念,而且递归函数也很难调试并且消耗大量的堆栈空间。 因此,在实际的C语言程序开发中,除非递归能够带来很大的便利,否则并不建议使用递归,而是尽可能使用循环来解决问题。

在过去的几十年里,大量的编程语言被发明、替换、修改或组合在一起。 尽管人们曾多次尝试创建通用编程语言,但这些尝试都没有成功。 之所以有这么多不同的编程语言,其实是因为编写程序的初衷不同; ,不同程序的运行成本 ( ) 不同。

 
反对 0举报 0 收藏 0 打赏 0评论 0
 
更多>同类资讯
推荐图文
推荐资讯
点击排行
网站首页  |  关于我们  |  联系方式  |  使用协议  |  版权隐私  |  网站地图  |  排名推广  |  广告服务  |  积分换礼  |  网站留言  |  RSS订阅  |  违规举报
Powered By DESTOON