c语言学习记录——函数递归

一、递归的概念

是指函数/过程/子程序在运行过程序中直接或间接调用自身而产生的重入现象。

在计算机编程里,递归指的是一个过程:函数不断引用自身,直到引用的对象已知。

通俗的说就是函数体自己调用自己的情况,叫做递归。

递归在一定情况下可以快速解决很多问题,让代码更加简洁。实际上所有的递归算法都可以转化为和它等价的非递归算法。

二、常见的递归问题

1、Fibonacci数列

设An是一个数列,当n<=2时,An=1;当n>2时,满足等式An = An-1+An-2,也就是说当n大于2时,每一项都等于前两项的和。这样的数列称为Fibonacci数列,也成为“兔子数列”。

如何在c语言中求Fibonacci数列的每一项呢?

可以定义一个函数Fibo,输入一个正整数n作为参数,由函数满足的等式Fibo(n)=Fibo(n-1)+Fibo(n-2),不难发现函数体自己调用了自己,所以它是一个递归问题。

上述等式只有在n>2时满足,当n<=2时应该让函数返回值1。具体的代码实现如下——

#define  _CRT_SECURE_NO_WARNINGS 
#include<stdio.h>
//用递归的方式求斐波那契数
fibo_num(unsigned int n)
{
	if (n <= 2)
		return 1;
	else
		return fibo_num(n - 1) + fibo_num(n - 2);
}
int main()
{
	unsigned int n = 0;
	scanf("%d", &n);
	int ret = fibo_num(n);
	printf("%d", ret);
	return 0;

}

刚刚说过,任何的递归算法都可以转化为和它等价的非递归算法。

Fibonacci数列的非递归算法思路:定义三个整形值a,b,c。(c代表数列的第n项,a和b分别是c的前两项)

当n>2时候,c = b+a,而前两项b和a也要分别往前算它们的前两项,所以每次加的时候都要把c赋给b,b赋给a,放入一个循环体中,每次循环都让循环变量n减1。具体代码实现如下——

#define  _CRT_SECURE_NO_WARNINGS 
#include<stdio.h>
//用递归的方式求斐波那契数
fibo_num(unsigned int n)
{
	if (n <= 2)
		return 1;
	else
		return fibo_num(n - 1) + fibo_num(n - 2);
}
int main()
{
	unsigned int n = 0;
	scanf("%d", &n);
	int ret = fibo_num(n);
	printf("%d", ret);
	return 0;

}

2、汉诺塔问题

有三根相邻的柱子,标号为A,B,C,A柱子上从下到上按金字塔状叠放着n个不同大小的圆盘,要把所有盘子一个一个移动到柱子B上,并且每次移动同一根柱子上都不能出现大盘子在小盘子上方,请问至少需要多少次移动,设移动次数为H(n)。

n为1时 Hn= 1,n为2时Hn= 3,n为3时Hn=7.。。。。。。

则H(n)满足的关系式子为,H(n)=2*H(n-1)+1(n>2)

代码实现如下——

#define  _CRT_SECURE_NO_WARNINGS 
#include<stdio.h>

num(unsigned int n)
{
	if (n == 1)
		return 1;
	if (n > 1)
		return 2*num(n - 1) + 1;
}
int main()
{
	unsigned int n = 0;
	scanf("%d", &n);
	int ret = num(n);
	printf("%d", ret);
	return 0;

}

当然它也有等价的非递归代码——

#define  _CRT_SECURE_NO_WARNINGS 
#include<stdio.h>

num(unsigned int n)
{
	int a = 1;
	int c = 0;
	if (n == 1)
		return 1;
	while (n > 1)
	{
		c = 2 * a + 1;
		a = c;
		n--;
	}
	return c;
}
int main()
{
	unsigned int n = 0;
	scanf("%d", &n);
	int ret = num(n);
	printf("%d", ret);
	return 0;

}

上一篇:2-1 C++内置类型


下一篇:css004 用样式继承节省时间