C语言刷题(8)

1、关于递归的描述错误的是:(	)
 
A.存在限制条件,当满足这个限制条件的时候,递归便不再继续

B.每次递归调用之后越来越接近这个限制条件

C.递归可以无限递归下去

D.递归层次太深,会出现栈溢出现象

答案解析:

递归的两个条件:

 1. 将问题转化为其子问题,子问题要与原问题具有相同的解法

 2. 递归的出口

A:正确,限制条件即递归的出口,如果限制条件满足,递归程序就可以退出了

B:正确,因为每次递归,都是将原问题进一步缩小,缩小到限制条件时,就可以往回返,直到第一次递归调用

  比如:递归求和
int Sum(int N)
   {
     if(N == 1)
       return 1;
       
     return Sum(N-1)+N;
   }



假设:求Sum(4)的递归调用过程
   Sum(4)<----
        |       |
        |       |
      Sum(3)<----
        |       |
        |       |
      Sum(2)<----
        |       |
        |       |
      Sum(1)-----

 C:错误,递归不能无限递归下去,否则会造成死循环和栈溢出

 D:正确,因为每次递归,相当于都是一次新的函数调用,而每次函数调用系统必须给该函数划分栈帧空间,内部的递归函数没有退出,上层的递归就不能退出,栈帧就会累积许多块,如果累积超过栈的总大小,就会栈溢出。

2、关于函数的声明和定义说法正确的是:( )

A.函数的定义必须放在函数的使用之前

B.函数必须保证先声明后使用

C.函数定义在使用之后,也可以不声明

D.函数的声明就是说明函数是怎么实现的

答案解析:

A:错误,函数的定义可以放在任意位置,函数的声明必须放在函数的使用之前

B:正确

C:错误,函数定义在使用之后,使用之前没有声明时,编译器编译时识别不了该函数

D:错误,函数的声明只是告诉编译器函数返回值类型、函数名字以及函数所需要的参数,函数定义才是
说明函数是怎么实现的

3、根据下面递归函数:调用函数Fun(2),返回值是多少(  )
 
int Fun(int n)      
{ 
  if(n==5)   
    return 2;     
  else     
    return 2*Fun(n+1);      
}

A.2

B.4

C.8

D.16

答案解析:

Fun(2)--->返回16
 return 2*Fun(3)  2*8=16
      |__Fun(3):8
         return 2*Fun(4)  2*4=8
              |__Fun(4):4
                 return 2*Fun(5) 2*2=4
                      |__Fun(5):2  
                         return 2

因此,选择D

4、计算斐波那契数

递归和非递归分别实现求第n个斐波那契数
例如:
输入:5  输出:5
输入:10, 输出:55
输入:2, 输出:1


/*
思路:
一个问题直接求解时不好求解,如果可以将其划分成其子问题,并且子问题和原问题有相同的解法时,就可以使用递归的方式解决
递归的两个条件:
 1. 将问题划分成其子问题,要求:子问题要与原问题具有相同的解法
 2. 递归的出口
              1                 N < 3              
Fac(N)      
       Fac(N-1) + Fac(N-2)     N >= 3
*/


long long Fac(int N)
{
 if(N < 3)
     return 1;
 
 return Fac(N-1) + Fac(N-2);
}

5、递归实现n的k次方

编写一个函数实现n的k次方,使用递归实现。

/*
思路:
          1      K==0
Pow(n,K) = 
          Pow(n, K-1)*n
          
*/
int Pow(int n, int k)
{
	if(k==0)
		return 1;
	else if(k>=1)
	{
		return n*Pow(n, k-1);
	}
}

6、计算一个数的每位之和(递归实现)

写一个递归函数DigitSum(n),输入一个非负整数,返回组成它的数字之和
例如,调用DigitSum(1729),则应该返回1+7+2+9,它的和是19
输入:1729,输出:19

/*
思路:
            n    n < 10
DigiSum(n) = 
           DibiSum(n/10)+n%10   // 前n-1位之和+第N位
*/


int DigitSum(int n)//1729
{
	if(n>9)
		return DigitSum(n/10)+n%10;
	else
		return n;
}

7、字符串逆序(递归实现)

编写一个函数 reverse_string(char * string)(递归实现)
实现:将参数字符串中的字符反向排列,不是逆序打印。
要求:不能使用C函数库中的字符串操作函数。

比如:
char arr[] = "abcdef";
逆序之后数组的内容变成:fedcba

/*
思路:
逆置字符串,循环的方式实现非常简单
  1. 给两个指针,left放在字符串左侧,right放在最后一个有效字符位置
  2. 交换两个指针位置上的字符
  3. left指针往后走,right指针往前走,只要两个指针没有相遇,继续2,两个指针相遇后,逆置结束
*/
void reverse_string(char* arr)
{
	char *left = arr;
	char *right = arr+strlen(arr)-1;


	while(left=2)
		reverse_string(arr+1);
 
	*(arr+len-1) = tmp;
}

8、strlen的模拟(递归实现)

递归和非递归分别实现strlen

/*
strlen的含义是:求字符串中有效字符的长度,不包括\0。
*/


/*
循环实现:
1. 给一个计数,用来统计有效字符的个数
2. 遍历字符串,只要没有遇到\0, 遇到一个字符给计数加1,直到遇到\0
*/


 int my_strlen(char* str)
 {
 	int count = 0;
 	while('\0' != *str)
 	{
 		count++;
 		str++;
 	}
 	return count;
 }




/*
递归实现:
                0  *str == '\0' 
my_strlen(str)
                my_strlen(p+1) + 1  子问题划分
*/
int my_strlen(char *str)
{
	if('\0' == *str)
		return 0;
	else
		return 1+my_strlen(1+str);
}
9、求阶乘

递归和非递归分别实现求n的阶乘(不考虑溢出的问题)

/*
Fac(N) = 1*2*3*……*N


递归方式实现:
        1    N <= 1
Fac(N)
        Fac(N-1)*N    N >= 2
*/


long long Fac(int N)
{
    if(N <= 1)
        return 1;
    
    return Fac(N-1)*N;
}


/*
循环方式:从1乘到N即可
*/
long long Fac(int N)
{
    long long ret = 1;
    for(int i = 2; i <= N; ++i)
    {
        ret *= i;
    }
    
    return ret;
}

10、打印一个数的每一位

递归方式实现打印一个整数的每一位

/*
思路:
              N   N <= 9
Print(N)
              Print(N-1), 打印N
*/

 void print(unsigned int n)
 {
 	if(n>9)
 		print(n/10);
 	printf("%d ", n%10);
 }

你可能感兴趣的:(C语言,C语言刷题,刷题之路,c语言,java,算法,开发语言,c++,数据结构)