c语言递归函数怎么写( 三 )


函数介绍:
在数理逻辑和计算机科学中,递归函数或μ-递归函数是一类从自然数到自然数的函数,它是在某种直觉意义上是"可计算的"。事实上,在可计算性理论中证明了递归函数精确的是图灵机的可计算函数 。递归函数有关于原始递归函数,并且它们的归纳定义(见下)建造在原始递归函数之上 。但是,不是所有递归函数都是原始递归函数 — 最著名的这种函数是阿克曼函数 。
其他等价的函数类是λ-递归函数和马尔可夫算法可计算的函数 。
例子:
//代码1
void func()
{
// 。
if( 。)
func();
else
// 。
}
条件:
一个含直接或间接调用本函数语句的函数被称之为递归函数,在上面的例子中能够看出,它必须满足以下两个条件:
1) 在每一次调用自己时,必须是(在某种意义上)更接近于解;
2) 必须有一个终止处理或计算的准则 。
梵塔的递归函数:
//C
void hanoi(int n,char x,char y,char z)
{
if(n==1)
move(x,1,z);
else
{
hanoi(n-1,x,z,y);
move(x,n,z);
hanoi(n-1,y,x,z);
}
}
8.C语言函数递归 几乎每一本C 语言基础的书都讲到了函数递归的问题,但是初学者仍然容易在这个地方犯错误 。
先看看下面的例子:void fun(int i){ if (i>0) { fun(i/2); } printf("%d\n",i);}intmain(){ fun(10); return 0;}问:输出结果是什么?这是我上课时,一个学生问我的问题 。他不明白为什么输出的结果会是这样:012510他认为应该输出0 。
因为当i 小于或等于0 时递归调用结束,然后执行printf 函数打印i 的值 。这就是典型的没明白什么是递归 。
其实很简单,printf("%d\n",i);语句是fun 函数的一部分,肯定执行一次fun 函数,就要打印一行 。怎么可能只打印一次呢?关键就是不明白怎么展开递归函数 。
展开过程如下:void fun(int i){ if (i>0) { //fun(i/2); if(i/2>0) { if(i/4>0) { … } printf("%d\n",i/4); } printf("%d\n",i/2); } printf("%d\n",i);}这样一展开,是不是清晰多了?其实递归本身并没有什么难处,关键是其展开过程别弄错了 。二、不使用任何变量编写strlen 函数看到这里,也许有人会说,strlen 函数这么简单,有什么好讨论的 。
是的,我相信你能熟练应用这个函数,也相信你能轻易的写出这个函数 。但是如果我把要求提高一些呢:不允许调用库函数,也不允许使用任何全局或局部变量编写intmy_strlen (char *strDest);似乎问题就没有那么简单了吧?这个问题曾经在网络上讨论的比较热烈,我几乎是全程“观战”,差点也忍不住手痒了 。
不过因为我的解决办法在我看到帖子时已经有人提出了,所以作罢 。解决这个问题的办法由好几种,比如嵌套有编语言 。
因为嵌套汇编一般只在嵌入式底层开发中用到,所以本书就不打算讨论C 语言嵌套汇编的知识了 。有兴趣的读者,可以查找相关资料 。
也许有的读者想到了用递归函数来解决这个问题 。是的,你应该想得到,因为我把这个问题放在讲解函数递归的时候讨论 。
既然已经有了思路,这个问题就很简单了 。代码如下:intmy_strlen( const char* strDest ){ assert(NULL != strDest); if ('\0' == *strDest) { return 0; } else { return (1 + my_strlen(++strDest)); }}第一步:用assert 宏做入口校验 。
第二步:确定参数传递过来的地址上的内存存储的是否为'\0' 。如果是,表明这是一个空字符串,或者是字符串的结束标志 。
第三步:如果参数传递过来的地址上的内存不为'\0',则说明这个地址上的内存上存储的是一个字符 。既然这个地址上存储了一个字符,那就计数为1,然后将地址加1 个char类型元素的大小,然后再调用函数本身 。