(本文接续上文http://t.csdn.cn/btk8T)
目录:非递归 递归和非递归的区别 防止栈溢出的方法 函数栈帧
(7)非递归 即为不是递归的,内常用迭代(也就是循环)
(8)递归和非递归的比较
递归 :优点: 可以把一个大问题分解成一个个的小问题,减化代码量,
缺点:计算机无脑套入,导致运算量大,所以容易会栈溢出 (下面,在拓展上面有解释以前也解释过),也就是无法使用,计算。
非递归:优点:可以减轻计算机的计算量,不容易栈溢出。
缺点:对于问题理解不到位会写出一堆代码(很冗余)而且·这一部分需要程序员自己计算化简之后,再写入程序内。题目越难,越难写出来,越长。
总结: 1. 许多问题是以递归的形式进行解释的,这只是因为它比非递归的形式更为清晰。
2. 但是这些问题的迭代实现往往比递归实现效率更高,虽然代码的可读性稍微差些。
3. 当一个问题相当复杂,难以用迭代实现时,此时递归实现的简洁性便可以补偿它所带来的运行时开 销。
例如:用函数写求第n个斐波那契数
利用递归写
int fib(int n)
{
if (n <= 2)
return 1;
else
return fib(n - 1) + fib(n - 2);
}
用非递归写
int count = 0;
int fib(int n)
{
if(n == 3)
count++;
if (n <= 2)
return 1;
else
return fib(n - 1) + fib(n - 2);
}
当利用较大的数计算时最后的结果,第一个就算不出来,第二个可以算出来。
(9)总结一下,防止栈溢出方法。
1. 将递归改写成非递归。
2. 使用static对象替代 nonstatic 局部对象。在递归函数设计中,可以使用 static(变为静态变量放到静态区) 对象替代 nonstatic 局部对象(即栈对象),(但是此做法作用微乎其微)。
内存分为三个区:栈区 堆区 静态区 局部变量默认放到栈区,当栈区满了就会溢出。
拓展,函数栈帧的创建和销毁:(尽量理解,不需要必须理解)(以下以汇编代码,16进制表示)
(首先声明,函数栈帧问题的演示方法各编译器下可能不同,但是大同小异)(本文章用vs2013演示)
首先说一下寄存器分为五种:eax ebx ecx edx ebp esp。
而后两个则是维护函数栈帧的。
每一个函数调用都需要在栈区(在内存中)有一个空间,从其中的高地址到低地址
esp ebp两个寄存器会自动维护正在使用的函数调用。
以下用main函数讲解:
在一开始时就会确定两个位置为两个寄存器放的位置,而当读取到函数的内容时寄存器则会变化位置 call是调用
该图为上面的代码,然后该图右面为进行步骤
1到2为移动