递归的应用
1.用递归实现从0到n
(1)
void f1(int n){
if (n > 0) {
f1(n-1);//打印0-(n-1)
}
printf("%d\n", n);
}
(2)
void f2(int begin,int end){
if (begin > end) {
return;
}
printf("%d\n",begin);
f2(begin+1, end);
}
2.计算数组a从下标begin开始到下标end的元素和
(1)
int f3(int a[],int begin, int end){
if (begin == end) {
return 0;
}
int x = f3(a, begin+1, end);
return x + a[begin];
}
(2)
int f4(int a[],int end){
if (end ==0) {
return 0;
}
int x = f4(a, end-1);
return x + a[end];
}
3.用递归实现两个字符串是否相同,从前往后进行比较
int f5(char *str1,char *str2){
if (strlen(str1) != strlen(str2)) {
return 0;
}
if (strlen(str1) ==0) {
return 1;
}
if (str1[0] != str2[0]) {
return 0;
}
return f5(str1+1, str2+1);
}
4.在n个球中任意取出m个(不放回),求多少种取法
int f6(int n, int m){
if ( n < m) {
return 0;
}
if (n == m) {
return 1;
}
if (m == 0) {
return 1;
}
return f6(n-1, m-1)+f6(n-1, m);//n个球中有一个特殊球x,取划分,包含这个x球为f6(n-1, m-1),不包含这个球为f6(n-1, m)
}
5.求n的球的全排列
void f7(char a[],int k , int n){//k表示当前位置与后面的元素交换
char ch;
if(k == n ){
for (int i =0; i < n; i++) {
printf("%c",a[i]);
}
printf("\n");
}else{
for (int i = k; i < n; i++) {//将第k个元素与后面的元素交换,然后调用f7
if(k != i){
ch = a[k];
a[k] = a[i];
a[i] = ch;//试探
}
f7(a, k+1, n);
if (k != i) {
ch = a[k];
a[k] = a[i];
a[i] = ch;//回溯
}
}
}
}
6.求两个串的最大公共子序列(可以不连续)
int f8(char *str1,char *str2){
if (strlen(str1) ==0 || strlen(str2) ==0) {
return 0;
}
if (str1[0] == str2[0]) {
return f8(str1+1, str2+1)+1;
}else{
return f8(str1+1, str2)>f8(str1, str2+1) ?f8(str1+1, str2) :f8(str1, str2+1);
}
}
7.求一个字符串的反串
void change(char str[])
{
if(*str=='\0')return;
change(str+1);
printf("%c",*str);
}
8.计算杨辉三角的第m层的第n元素,m,n从零开始
int f9(int m,int n){
if (m == 0) {
return 1;
}
if (n == m || n == 0) {
return 1;
}
return f9(m-1, n)+f9(m-1, n-1);
}
9.m个A和n个B可以有多少种排列
int f9(int m,int n){
if (m == 0) {
return 1;
}
if (n == m || n == 0) {
return 1;
}
return f9(m-1, n)+f9(m-1, n-1);
}
递归需要注意的几点:
1.递归每次调用的层次不同
2.递归每次调用的形式参数不同
3.注意返回的次序
=======================================================================================================近期看了《C和指针》里面有一部分简单介绍了递归,感觉对递归又有了新的理解。
记得再我学习C语言的时候,学校的教科书上就是以求阶乘和菲波那切数列为例,编写了相关的代码,但是在求阶乘的函数中递归并没有战术任何优越之处,而在斐波那契数列中,其效率更是极其的低。
使用递归需要的两个特性:
1.存在限制条件,当符合这个限制条件的时候就不在进行递归。
2.每次递归调用之后越来越来接近这个条件限制。
许多问题是以递归形式进行解释和定义的,这样问题就会更清晰。但是,这些问题用迭代的方式实现的时候效率会更高,即使代码的可读性会差一些。当你阅读递归函数的时候,不必纠缠于递归函数的内部调用的细节,只需认为他实现了特定的任务即可。
如果一个递归函数内部所执行的最后一个条语句就是调用自身的话,这个函数就被称为尾部递归,可以很容易的改写成迭代循环的形式,效率会更高一些。
用迭代求阶乘
long factorial ( int n )
{
long result = 1;
while ( n > 1 ) {
result *= n--;
}
return result;
}
用迭代求斐波那契数列
long fibonacci ( int n )
{
long result = 1;
long pre_result = 1;
long temp_result = 0;
while ( n-- > 2)
{
temp_result = result;
result += pre_result;
pre_result = temp_result;
}
return result;
}