1. 程序调用自身的编程 技巧称为递归
2. 递归的主要思考方式:把大事化小
3. 递归的定义:
a. 若一个对象部分地包含它自己,或用它自己给自己定义,则称这个对象是递归的
b. 若一个过程直接地或间接地调用自己,则称这个过程是递归的过程
4. 需用到递归的三种情况:
a. 定义是递归的,如树的数据结构就是递归的
b. 数据结构是递归的
c. 问题的解法是递归的
5. 递归的理解:
递归的基本思想是:自己调用自己
如果一个问题中具有以下特点:
a. 有一个初始状态
b. 后续的情况可由前面的状态推出
则可以用递归的方法求解
6. 在使用递归时,可以先列出其数学公式:
例如:求解 n!
代码实现:
int factorial(int n)
{
if(n <= 1)
return 1;
else
return n * factorial(n-1);
}
7. 递归的俩个必要条件:
a.存在限制条件,当满足这个限制条件的时候,递归便不再继续
b.每次递归调用之后越来越接近这个限制条件
8. 递归也是一种算法:
许多问题是以递归的形式进行解释的,这只是因为它比非递归的形式更为清晰
但是这些问题的迭代实现往往比递归实现效率更高,虽然代码的可读性稍微差些
当一个问题相当复杂,难以用迭代实现时,此时递归实现的简洁性便可以补偿它所带来的运行时开销
9. 递归与循环:
可以使用循环的地方通常都可以使用递归
10. 递归的基本原理:
a. 每级函数调用都有自己的变量。即,第一级的数值与第二级的数不同
b. 每次函数调用都会返回一次。当函数执行完毕后,控制权将被传回上一级递归。程序必须按顺序逐级返回递归(这一点可从堆栈或数学上的公式来理解)
c. 递归函数中位于递归调用之前的语句,均按被调函数的顺序执行
d. 递归函数中位于递归调用之后的语句,均按被调函数相反的顺序执行
e. 虽然每级递归都有自己的变量,但是并没有拷贝函数的代码。程序按顺序执行函数中的代码,而递归调用就相当于又从头开始执行函数的代码。
除了为每次递归调用创建变量外,递归调用非常类似于一个循环语句,实际上,递归有时可用循环来代替,循环有时也可以用递归来代替
f. 通常递归函数都使用 if 或其他等价的测试条件在函数形参等于某特定值时终止递归。为此,每次递归调用的形参都要使用不同的值
11. 递归与迭代的区别:
递归是一个树结构,从字面可以其理解为重复“递推”和“回归”的过程,当“递推”到达底部时就会开始“回归”,其过程相当于树的深度优先遍历。
迭代是一个环结构,从初始状态开始,每次迭代都遍历这个环,并更新状态,多次迭代直到到达结束状态。
经典例题:
求第n个斐波那契数。(不考虑溢出)
int fib(int n)
{
if (n <= 2)
return 1;
else
return fib(n - 1) + fib(n - 2);
}
编写函数不允许创建临时变量,求字符串的长度
#incude <stdio.h>
int Strlen(const char*str)
{
if(*str == '\0')
return 0;
else
return 1+Strlen(str+1);
}
int main()
{
char *p = "abcdef";
int len = Strlen(p);
printf("%d\n", len);
return 0;
}
接受一个整型值(无符号),按照顺序打印它的每一位
例如:
输入 :1234,输出 1 2 3 4
#include <stdio.h>
void print(int n)
{
if(n>9)
{
print(n/10);
}
printf("%d ", n%10);
}
int main()
{
int num = 1234;
print(num);
return 0;
}