递归和迭代
这两个概念也许很多童鞋依旧分不清楚,下面通过求解斐波那契数来看看它们俩的关系吧。
斐波那契数的定义:
递归:
(factorial 6)
(* 6 (factorial 5))
(* 6 (* 5 (factorial 4)))
(* 6 (* 5 (* 4 (factorial 3))))
(* 6 (* 5 (* 4 (* 3 (factorial 2)))))
(* 6 (* 5 (* 4 (* 3 (2 (factorial 1))))))
(* 6 (* 5 (* 4 (* 3 (* 2 1)))))
(* 6 (* 5 (* 4 (* 3 2))))
(* 6 (* 5 (* 4 6)))
(* 6 (* 5 24))
(* 6 120)
720
迭代:
(factorial 6)
(factorial 1 1 6)
(factorial 1 2 6)
(factorial 2 3 6)
(factorial 6 4 6)
(factorial 24 5 6)
(factorial 120 6 6)
(factorial 720 7 6)
720
递归的核心在于:不断地回到起点。
迭代的核心在于:不断地更新参数。
在下面的代码中:
递归的核心是sum的运算,sum不断的累乘,虽然运算的数值不同,但形式和意义一样。
而迭代的核心是product和counter的不断更新。如上表中,product就是factorial的前2个参数不断的累乘更新成第一个参数;而第二个参数则是counter,其不断的加1来更新自己。
product <- counter * product
counter < - counter + 1
#include <iostream>
using namespace std;
int factorialRecursive(int n);
int factorialIteration(int product, int counter, int max_count);
int main()
{
int n;
cout<<"Enter an integer:"<<endl;
cin>>n;
cout<<factorialRecursive(n)<<endl;
cout<<factorialIteration(1,1,n)<<endl;
return 0;
}
int factorialRecursive(int n)
{
int sum=1;
if(n==1)
sum*=1;
else
sum=n*factorialRecursive(n-1);
return sum;
}
int factorialIteration(int product, int counter, int max_count)
{
int sum=1;
if(counter>max_count)
sum*=product;
else
factorialIteration((counter*product),(counter+1),max_count);
}
补充问题:
关于上面的factorialIteration函数,今天收到一份邮件,我也通过再次分析学到了很多,这里罗列一下。
第一个问题:
首先来看相对简单的问题,该童鞋在函数内以两种不同方式加上another_sum=2却有着不同的结果。
int factorialIteration(int product, int counter, int max_count)
{
int sum=1;
int another_sum=2;
if(counter>max_count)
{
sum*=product;
another_sum*=product;
}
else
factorialIteration((counter*product),(counter+1),max_count);
}
int factorialIteration(int product, int counter, int max_count)
{
int sum=1;
int another_sum=2;
if(counter>max_count)
{
another_sum*=product;
sum*=product;
}
else
factorialIteration((counter*product),(counter+1),max_count);
}
因为这个函数声明的是int型的返回类型,但没有用return语句,所以C++自动将其运行的最后一行语句作为了返回语句。所以这两个函数类似于:
int factorialIteration(int product, int counter, int max_count)
{
int sum=1;
int another_sum=2;
if(counter>max_count)
{
sum*=product;
return another_sum*=product;
}
else
factorialIteration((counter*product),(counter+1),max_count);
}
int factorialIteration(int product, int counter, int max_count)
{
int sum=1;
int another_sum=2;
if(counter>max_count)
{
another_sum*=product;
return sum*=product;
}
else
factorialIteration((counter*product),(counter+1),max_count);
}
然而我在CodeBlocks中写的代码不用return是可以的,但在Visual Studio中却是会报错的。
有了这个发现,我原来的代码也可以这样来写:
#include <iostream>
using namespace std;
int factorialRecursive(int n);
int factorialIteration(int product, int counter, int max_count);
int main()
{
int n;
cout<<"Enter an integer:"<<endl;
cin>>n;
cout<<factorialRecursive(n)<<endl;
cout<<factorialIteration(1,1,n)<<endl;
return 0;
}
int factorialRecursive(int n)
{
int sum=1;
if(n==1)
sum*=1;
else
sum=n*factorialRecursive(n-1);
// return sum; // 去掉这里的return语句
}
int factorialIteration(int product, int counter, int max_count)
{
int sum=1;
if(counter>max_count)
return sum*=product; // 在这里加上return语句
else
factorialIteration((counter*product),(counter+1),max_count);
}
现在来看另一个问题:
#include <iostream>
using namespace std;
int test(int n);
int sum;
int main()
{
cout<<test(1)<<endl;
return 0;
}
int test(int n)
{
sum = 1;
sum += n;
if (sum < 5)
test(n+1);
}
如果设sum为全局变量,那么会在test函数中每一次调用sum=1时都将sum重新赋值为1。整个程序最后输出为5。这个应该没有什么悬念吧?
如果设sum给test内的局部变量,则会在每一次执行int sum=1语句时都会创建一个新的sum对象,它的存放地址和之前的sum并不相同。然后整个程序最后输出意外的是4。
#include <iostream>
using namespace std;
int test(int n);
int main()
{
cout<<test(1)<<endl;
return 0;
}
int test(int n)
{
int sum = 1;
sum += n;
if (sum < 5)
return test(n+1);
// return sum; 此处有这一行代码命名为程序1,没有这行代码命名为程序2
}
程序1的输出是5,程序2的输出是4。具体函数执行过程如下:
第一步,调用test(1):
int sum=1
sum=2
return test(2)
第二步,调用test(2):
int sum=1
sum=3
return test(3)
第三步,调用test(3):
int sum=1
sum=4
return test(4)
第四步,调用test(4):
int sum=1
sum=5
执行到第四步的时候,由于sum以及不比5小了,所以程序1没有进入if语句而是执行下一句return sum,所以输出为1。
而如果是程序2,也就是没有return sum语句,那么程序在执行完第四步后就会返回到第三步,最终调用(return) sum=4,输出4。
第三个问题:
该童鞋还提到了尾递归,这里我就来说说我的理解,如有问题欢迎大家直接评论或邮件给我。
上面代码中的递归函数factorialRecursive应该没问题的吧。
上面的代码我给其命名为迭代。
int factorialIteration(int product, int counter, int max_count)
{
int sum=1;
if(counter>max_count)
sum*=product;
else
factorialIteration((counter*product),(counter+1),max_count);
}
通过在main函数中调用如下代码来执行该函数:
cout<<factorialIteration(1,1,n)<<endl;
当然,也可以另外写一个函数如下:
int factorialIter(int n)
{
return factorialIteration(1,1,n);
}
并通过在main函数中直接调用该函数来做计算:
cout<<factorialIter(n)<<endl;
函数factorialIteration中的max_count我们称其为“循环不变量”,也就是对于整个运算过程而言这个变量是不变的。为了让大家更加印象深刻,将前面出现过的东西再来复制一遍:
(factorial 6)
(factorial 1 1 6)
(factorial 1 2 6)
(factorial 2 3 6)
(factorial 6 4 6)
(factorial 24 5 6)
(factorial 120 6 6)
(factorial 720 7 6)
720
从第二行开始的factorial的第三个参数”6“就是循环不变量。
尾递归&