函数的递归
文章目录
什么是递归
递归的主要思想
递归的两个必要条件
递归与迭代的关系与选择
递归与迭代共同解斐波那契数列
//递归法求斐波那契数列
#include<stdio.h>
int Fib(int n)
{
if (n == 0)
{
return 0;
}
if (n <= 2)
{
return 1;
}
else
{
return Fib(n - 1) + Fib(n - 2);
}
}
int main()
{
int n = 0;
scanf("%d", &n);
int fibnum = Fib(n);
printf("%d", fibnum);
return 0;
}
要注意,在不考虑溢出的情况下我们计算第40个斐波那契数列,程序就需要等待好一会才能计算完毕,这效率显然不行,我们下面来看迭代法。
//迭代法求斐波那契数列
#include<stdio.h>
int main()
{
int n = 0;
int a = 1;
int b = 1;
int c = 1;
scanf("%d", &n);
if (n == 0)
{
printf("0\n");
}
else if (n <= 2)
{
printf("%d", c);
}
else
{
while (n>2)
{
c = a + b;
a = b;
b = c;
n--;
}
printf("%d", c);
}
return 0;
}
递归相关练习题
1.不创建临时变量求出字符串长度
上代码:
//递归求字符串长度
#include<stdio.h>
int my_strlen(char* str)
{
if (*str == '\0')
{
return 0;
}
else
{
return 1 + my_strlen(str + 1);
}
}
int main()
{
char arr[] = "Hello KissKernel!!!";
int num = my_strlen(arr);
printf("%d", num);
return 0;
}
2.递归实现n的阶乘
//递归实现n的阶乘
#include<stdio.h>
int Fac(int n)
{
if (n == 1)
return 1;
else
{
return n * Fac(n - 1);
}
}
int main()
{
int n = 0;
scanf("%d", &n);
int facnum = Fac(n);
printf("%d\n", facnum);
return 0;
}
3.递归实现逆序字符串
//递归实现逆序字符串
#include<stdio.h>
#include<string.h>
void reverse(char* first)
{
int sz = strlen(first);
static int n = 1;
char* end = first + sz - n;
if (first < end)
{
n++;
reverse(first + 1);
}
char tmp = *first;
*first = *end;
*end = tmp;
}
int main()
{
char arr[] = "Hello KissKernel!!!";
printf("%s\n", arr);//逆序前
reverse(arr);
printf("%s\n", arr);//逆序后
return 0;
}
这里设置的静态n是为了记录尾指针向前移动的数据,当然还有一种方法是进入函数直接逆序,将头字符保存起来,将尾字符置为’\0’,递归结束后在将头字符赋给尾字符;
代码如下:
//递归实现逆序字符串
#include<stdio.h>
#include<string.h>
void reverse(char* first)
{
int sz = strlen(first);
char* end = first + sz - 1;
char tmp = *first;
*first = *end;
*end = '\0';
if (*(first + 1) != '\0')
{
reverse(first + 1);
}
*end = tmp;
}
int main()
{
char arr[] = "Hello KissKernel!!!";
printf("%s\n", arr);//逆序前
reverse(arr);
printf("%s\n", arr);//逆序后
return 0;
}
4.递归实现n的k次方(有优化版本已更新)
#include<stdio.h>
int Sqr2(int n, int k)
{
if (k == 0)
{
return 1;
}
else
{
return n * Sqr2(n, k - 1);
}
}
int Sqr(int n, int k)
{
if (k == 0)
{
return 1;
}
else if(k%2 == 0)
{
return Sqr(n,k/2) * Sqr(n, k /2);
}
else
{
return n * Sqr(n, k - 1);
}
}
int main()
{
int n = 0;
int k = 0;
scanf("%d %d", &n, &k);
int ret = Sqr(n, k);
printf("%d\n", ret);
return 0;
}
优化方法,如果求得k次方为偶数,既可以转化为两个n的k/2次方的乘积;可以将时间复杂度从O(n)降低到O(logn)
5.青蛙跳台阶问题
//青蛙跳台阶问题
#include<stdio.h>
int Fun(int n)
{
if (n > 2)
{
return Fun(n - 1) + Fun(n - 2);
}
else
return n;
}
int main()
{
int n = 0;
scanf("%d", &n);
int num = Fun(n);
printf("%d", num);
return 0;
}
6.汉诺塔问题
//汉诺塔问题
#include<stdio.h>
int move = 0;
void Move(char n1, char n2)
{
move++;
}
void Fmove(int n, char a, char b, char c)//将a上的圆盘借助从b移动到c
{
if (n == 1)
{
Move(a, c);
}
else
{
Fmove(n - 1, a, c, b);//将a上的n-1个圆盘借助c移动到b;
Move(a, c);//将a上的圆盘放到c上;
Fmove(n - 1, b, a, c);//将b上的n-1个圆盘借助a移动到c上。至此移动结束
}
}
int main()
{
int n = 0;
char a = 'A';
char b = 'B';
char c = 'C';
scanf("%d", &n);
Fmove(n, a, b, c);
printf("%d\n", move);
return 0;
}