递归和迭代

参考链接:https://blog.csdn.net/gaoyu1253401563/article/details/82384958

从“编程之美”的角度看,可以借用一句非常经典的话:“迭代是人,递归是神!”来从宏观上对二者进行把握。

1. 递归

重复调用函数自身实现循环称为递归。
递归实际上不断地深层调用函数,直到函数有返回才会逐层的返回,递归是用栈机制实现的,每深入一层,都要占去一块栈数据区域,因此,递归涉及到运行时的堆栈开销(参数必须压入堆栈保存,直到该层函数调用返回为止),所以有可能导致堆栈溢出的错误;但是递归编程所体现的思想正是人们追求简洁、将问题交给计算机,以及将大问题分解为相同小问题从而解决大问题的动机。递归可以极大减少代码量,其能力在于用有限的语句来定义对象的无限集合。

例如:if else 调用自己,并在合适时机退出

构成递归所需条件:

  • 子问题须与原问题为同样的事,且更为简单;
  • 不能无限制地调用自身,须有个明确的递归出口,化简为非递归情况处理。

递归的经典案例:

  1. 斐波那契数列:
    又称黄金分割数列,指的是这样一个数列:1,1,2,3,5,8,13,21,…。这个数列从第三项开始,每一项都是前两项之和。
// 递归
int fA(int n){
	if(n<=0)
		return 0;
	else if(n==1 || n==2)
		return 1;
	else
		return f(n-1)+f(n-2);
}
  1. 求n的阶乘: n ! = n ∗ ( n − 1 ) ∗ ( n − 2 ) ∗ . . . ∗ 1 ; ( n > 0 ) n!=n*(n-1)*(n-2)*...*1;(n>0) n!=n(n1)(n2)...1;(n>0)
  2. 汉诺塔问题:
    递归和迭代_第1张图片

2. 迭代

利用变量的原值推出新值称为迭代,或着说迭代是函数内某段代码实现循环。
迭代大部分时候需要人为的对问题进行剖析,分析问题的规律所在,将问题转变为一次次的迭代来逼近答案。迭代不像递归那样对堆栈有一定的要求,另外一旦问题剖析完毕,就可以很容易的通过循环加以实现。迭代的效率高,但却不太容易理解,当遇到数据结构的设计时,比如图表、二叉树、网格等问题时,使用就比较困难,而是用递归就能省掉人工思考解法的过程,只需要不断的将问题分解直到返回就可以了。

例如:for,while循环

迭代的经典案例:

  1. 斐波那契数列:
// 迭代
int fB(int n){
	if(n <= 0)
		return 0;
	if(num == 1 || num == 2)
		return 1;
	int first = 1,second =1,third = 0;
	for(int i = 3; i<= num ;i++) {
		third = first + second;
		first = second;
		second = third;
	}
	return third;
}
  1. 汉诺塔问题:
  2. 背包问题:
    有N件物品和一个容量为V的背包。第i件物品的重量是w[i],价值为v[i]。求将哪些物品放入背包可使得这些物品的重量总和不超过背包容量,且价值总和最大。

3. 两者区别

递归与迭代的区别:递归中一定有迭代,但是迭代中不一定有递归。因此,所有的迭代可以转换为递归,但递归不一定可以转换成迭代。
简单来说,递归是重复调用函数自身实现循环,迭代是函数内某段代码实现循环。
在循环次数较大时,迭代的效率明显优于递归。
递归与普通循环的区别:循环是有去无回,而递归则是有去有回(存在终止条件)。
迭代与普通循环的区别:迭代时,循环代码中参与运算的变量同时是保存结果的变量,当前保存的结果作为下一次循环运算的初始值。

总结

定义 优点 缺点
递归 重复调用函数自身实现循环 a.用有限的循环语句实现无限集合;
b.代码易读;
c.大问题转化成小问题,减少了代码量
a.递归不断调用函数,浪费空间;
b.容易造成堆栈溢出
迭代 利用变量的原值推出新值;
函数内某段代码实现循环。
a.效率高,运行时间只随循环的增加而增加;
b.无额外开销
a.代码难理解;
b.代码不如递归代码简洁;
c.编写复杂问题时,代码逻辑不易想出
两者区别 a.递归中一定有迭代,但是迭代中不一定有递归;大部分可以相互转换。
b.相对来说,能用迭代不用递归(因为递归不断调用函数,浪费空间,容易造成堆栈溢出)

你可能感兴趣的:(C++)