目录
一.什么是递归?
程序调用自身的编程技巧成为递归(recursion)。
递归作为一种算法在程序设计语言中广泛应用。一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。
递归的主要思考方式在于:把大事化小。
递归的两个必要条件:
- 存在限制条件,当满足这个限制条件的时候,递归便不再继续。
- 每次递归调用之后越来越接近这个限制条件。
二.例题
1.接受一个整型值(无符号),按照顺序打印他的每一位。
例如:
输入:1234,输出:1 2 3 4.
#include<stdio.h>
#include<stdlib.h>
//打印这个数字的每一位
//x=>1234
void PrintNum(int x){
if(x>9){
//x多于一位
PrintNum(x/10);
}
//x就是1位数
printf("%d",x%10);
}
int main(){
PrintNum(1234);
system("pause");
return 0;
}
2.编写函数不允许创建临时变量,求字符串的长度。
(1)递归算法。
#include<stdio.h>
#include<stdlib.h>
#include<stdint.h>
int Strlen(char* str){
if(*str=='\0'){
//str指向的是一个空字符串
return 0;
}
//str指向的不是一个空字符串,当前字符是字符串中的一个元素
//hello ,str=>h 整个字符串的长度就为
//1+"ello"字符串的长度
return 1+Strlen(str+1);
}
int main(){
printf("%d\n",strlen("hello"));
system("pause");
return 0;
}
(2)非递归算法。
#include<stdio.h>
#include<stdlib.h>
#include<stdint.h>
//实现求一个字符串的长度
//C语言中的字符串是通过字符数组的形式来模拟的
//字符数组本质上就是一个普通的数组,只不过每个元素的类型是char
//C风格字符串,会在数组的最后一个元素中填充成 、0 作为字符串的结束标志
//虽然C语言的字符串是字符数组,但是很多情况下也可以使用一个
//char* 指向字符数组的第一个元素,然后用这个指针来表示字符串
int Strlen(char* str){
int count=0;
//解引用
while(*str!='\0'){
++count;
++str;
}
return count;
}
int main(){
// "hello"字符串,占用6个字节的空间
//但是字符串长度为5(没算\0)
printf("%d\n",Strlen("hello"));
system("pause");
return 0;
}
3.求n的阶乘。(不考虑溢出)
(1)递归算法。
#include<stdio.h>
#include<stdlib.h>
//1.先看 n 是不是1,如果是1直接返回1
//2.如果n不是1,计算n*Factor(n-1)
int Factor(int n){
if(n==1){
return 1;
}
return n*Factor(n-1);
}
int main(){
//珠脑速算
//1*2*#*4*5 =>120
printf("%d\n",Factor(5));
system("pause");
return 0;
}
(2)非递归算法。
#include<stdio.h>
#include<stdlib.h>
int Factor(int n){
int result=1;
for(int i=1;i<=n;++i){
result *= 1;
}
return result;
}
int main(){
//珠脑速算
//1*2*#*4*5 =>120
printf("%d\n",Factor(5));
system("pause");
return 0;
}
4.求第n项斐波那契数(不考虑溢出)。
斐波那契数列是指这样一个数列:1、1、2、3、5、8、13、21、34、……在数学上,斐波那契数列以如下被以递推的方法定义:F(1)=1,F(2)=1, F(n)=F(n-1)+F(n-2)(n>=3,n∈N*)。
(1)递归算法。
#include<stdio.h>
#include<stdlib.h>
//求第n项斐波那契数列
int Fib(int n){
if(n==1||n==2){
return 1;
}
return Fib(n-1)+Fib(n-2);
}
int main(){
printf("%d\n",Fib(6));
system("pause");
return 0;
}
(2)非递归算法。
#include<stdio.h>
#include<stdlib.h>
int g_count=0;
//求第n项斐波那契数列
//s
//ms 1s=>1000ms
//us 1ms=>1000us
//ns 1us=>1000ns
int Fib(int n){
if(n==1||n==2){
return 1;
}
//表示i-2项和i-1项的内容
int num1=1;
int num2=1;
int result=0; //最终的 第n项 的结果
for(int i=3;i<n;++i){
result=num1+num2;
num1=num2;
num2=result;
}
return result;
}
//解决一个问题,往往既可以使用递归的方式,也可以使用非递归(循环)的方式
//递归的方式代码通常更直观更简单,但是运行效率可能会较低
//非递归方式代码通常更繁琐,但是运行效率可能会较高
int main(){
printf("%d\n",Fib(40));
printf("%d\n",g_count);
system("pause");
return 0;
}
上述两种代码,一种是递归另外一种是非递归,相较于非递归而言,递归算法更简洁,但是其运行效率也可能相对较低,而非递归算法虽然写起来复杂,但是运行效率却相对来说要更好些。