一切循环都可看作递归
1.计算斐波那契数列第n位的值。
斐波那契数列:1,1,2,3,5,8,13,21,34,55…
循环算法:
int fun(int n)
{
int a = 1, b = 1, c = 1;
for (int i = 3; i <= n; ++i)
{
c = a + b;
a = b;
b = c;
}
return c;
//时间复杂度:O(n)
递归算法:
int fun(int n)
{
if (n <= 3) return 1;
else return fun(n - 1) + fun(n - 2);
}
上述算法存在重复求解项,时间复杂程度为2^n。以下算法可减少时间复杂度:
int func(int n,int a,int b)
{
if(n <= 2) return a;
else return func(n - 1, a + b, a)
}
int fun(int n)
{
int a = 1,b = 1;
return func(n, a, b);
}
主函数:
int main()
{
int n;
scanf_s("%d", &n);
printf("%d => %d ", n, fun(n));
return 0;
}
2.递归实现求最大公约数
循环
unsiged int fac(unsigned int a,unsigned int b)
{
while(b != 0)
{
int c = a % b;
a = b;
b = c;
}
return a;
}
递归
unsiged int fac(unsigned int a,unsigned int b)
{
if(b == 0) return a;
else return fac(b, a % b); //将b赋给a,a%b赋给b
}
3.打印整型数组元素
主函数
int main()
{
const int n = 10;
int ar[n] = { 12,23,34,45,56,67,78,89,98,100 };
Print_Ar(ar, n);
return 0;
}
循环实现
void Print_Ar(int* br, int n)
{
assert(br != nullptr);
while (n > 0)
{
printf("%d ", br[n - 1]);
--n;
}
}
递归实现
(1)先打印,后递归
void Print_Ar(int* br, int n)
{
assert(br != nullptr);
if (n > 0)
{
printf("%d ", br[n - 1]);
Print_Ar(br, n-1);
}
}
先打印,后递归,分别打印br[9],…,br[0].
(2)先递归,后打印
void Print_Ar(int* br, int n)
{
assert(br != nullptr);
if (n > 0)
{
Print_Ar(br, n-1);
printf("%d ", br[n - 1]);
}
}
先递归,后打印。在回退的过程中打印,分别打印br[0],…,br[9].
(3).递归实现的几个错误
一般来说,递归时不要出现自加,自减
错误示例1:(n - -)
void Print_Ar(int* br, int n)
{
assert(br != nullptr);
if (n > 0)
{
Print_Ar(br, n--); //ERROR
printf("%d ", br[n - 1]);
}
}
Print_Ar(br, n--);
printf("%d ", br[n - 1]);
n- -,先赋值再减:首先取n = 10,先将10赋给下一次Print_Ar(br,n)中的n,然后自减,打印br[9],下一次执行时,依旧是Print_Ar(br,10),如此往复,无限递归,导致栈溢出。
错误示例2:(- - n)
void Print_Ar(int* br, int n)
{
assert(br != nullptr);
if (n > 0)
{
Print_Ar(br, --n); //ERROR
printf("%d ", br[n - 1]);
}
}
(- -n):先自减再赋值。递归过程中分别将n = 9,…3,2,1,0赋给下一个函数,在回退时,n = 0不执行递归语句,回退一位,此时n为0,打印br[n-1]为br[-1],越界打印,会出现一个随机值,结果如下:
错误示例2如果先打印再递归,则正确:
void Print_Ar(int* br, int n)
{
assert(br != nullptr);
if (n > 0)
{
printf("%d ", br[n - 1]);
Print_Ar(br, --n);
}
}
依次打印br[9],br[8],…,br[0]。
4.在无序数组中查找给定值,返回其下标
主函数:
int main()
{
const int n = 10;
int ar[n] = {34,56,12,23,78,89,90,100,67,45}
int val;
scanf_s("%d", &val);
int pos = FindValue(ar, n, val);
return 0;
}
循环实现:
int FindValue(int* br, int n, int val)
{
assert(br != nullptr);
int pos = n - 1;
while(pos >= 0 && br[pos] != val)
{
--pos;
}
return pos;
}
递归实现:
int FindValue(int* br,int n,int val)
{
assert(br != nullptr);
if(n < 1 || br[n-1] = val) //n为0,或值等于val时,返回-1,或下标
{
return n-1;
}
else
{
return FindValue(br, n-1, val) //否则将n-1赋给n
}
}
易错:
...
else
{
FindValue(br, n-1, val) //否则将n-1赋给n
}
若无return ,则回退过程返回的数据无法接收哦。