递归程序的理解

时间:2022-11-09 23:38:44

递归是c语言里面一个很重要的知识点,它的引入可以实际解决一些普通算法不好解决的问题,比如汉诺塔,迷宫等一些涉及回溯的问题用递归就很容易解决,写出的程序较简短。然而程序的简短是以花费较多的机器时间和占用较多的内存空间为代价的,效率较低,在我们学c和数据结构的时候,里面的程序递归算法通常要比非递归算法效率低 ,起码我还没见过高的,哪位达人给我举个反例出来。

其实学习递归就像学程序一样,一个就是会读递归程序,一个就是会写递归程序,而下面就将围绕这两个方面展开

首先是读递归程序,在c语言中有一类内存分配叫做栈分配,主要用来分配局部变量或者子程序的运行结果 返回地址之类的。当一个子程序(过程或函数)运行期间调用另一个子程序时,在运行被调用子程序之前,系统要完成以下工作:将所有的实参数、返回地址等信息传递给被调用过程数据区保存(即入栈);为被调用过程的局部变量分配存储区并入栈;将控制转移到被调用子程序入口。而从被调用子程序返回调用子程序之前,系统应该完成以下工作:释放被调子程序的数据区(即出栈);依照被调子程序保存的上一层的返回地址将控制转移到调用程序中,继续向下执行。即系统将整个递归程序运行时所需的数据存放在一个工作栈中,每当调用一个子程序时,就为它在栈顶分配一个存储区;每当退出一个子程序时,就释放它的存储区,则当前正在运行的子程序的数据区一定在栈顶。从这里可以看出 其实递归的优势在于每一步可以使用上一步的操作结果,就像cpu中断的现场保护一样。(注:有人说这样会减少重复时间,但增加了数据的内部操作时间,实在不能理解可能自己很少写递归程序吧)根据这个原理我们在读程序的时候可以像cpu工作那样,画一个栈来模拟程序的运行,可以更好的理解程序。看下面例子

#include <stdio.h>

void rev_str(char *p);

void main()
{
rev_str("I am a student.");
}

void rev_str(char *p)
{
if ((p == (char *)NULL) || (*p == '/0'))
{
return;
}
else
{
rev_str(p + 1);
printf("%c", *p);
}
}

网上down的一个逆序输出字符串的递归程序,程序第一步执行将当前参数 和运行的结果入栈  即参数*p='I',和输出结果I  放到栈底,我们写成(p,'i'),第2 3 4步的结果分别是(p+1,' ')(p+2,'a')(p+3,'m'),这样依次下去直到碰到'/0';时递归调用结束,从栈顶依次弹出结果,得到 ".tneduts a ma I"。

另外就是写递归程序,首先要看什么样的适合些递归程序,首先是回溯,再就是有递归表达式,比如说n得用n-1来表示这样,因为自己实在没写过什么所以不敢在往下唠叨,这里附上一个题目,自己编编加深对递归的理解。

http://community.csdn.net/Expert/topic/5220/5220911.xml?temp=.3779108