C中几个递归问题

版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/dcrmg/article/details/83583288

1. 计算累和 1+2+3+……+n

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int add_up(int n){
    if(n==1){
        return 1;
    }
    return n+add_up(n-1);
}

void main()
{
    int n=5;
    printf("%d\n",add_up(n));
    return;
}


2. 计算累乘 N!

递归方法:

int funN(int N)
{
    if (1>=N)
    {
        return 1;
    }
    else
    {
        return N*funN(N-1);
    }
}

非递归方法:

int funN(int N)
{
    int i,val = 1;
    if (N<=0)
    {
        return 0;
    }

    for(i=1;i<=N;i++)
    {
        val*=i;
    }
    return val;    
}


3. 素数判断

质数又称素数。一个大于1的自然数,除了1和它自身外,不能整除其他自然数的数叫做质数;

定义判别法:

#include<stdio.h>
#include<stdlib.h>

int isprime(int val)
{
    int n = 2;
    for(n; n<val;n++){
        if(val%n==0){
            return 0;
        }
    }
    return 1;   
}

int main()
{
    for(int i = 2;i<=100;i++){
        if(isprime(i)==1){
            printf("%d\n",i);
        }
    }
    return 0;
}


4. 递归实现十进制数转换成二进制数

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void to_binary(int num){
    int bin=num%2;
    if(num>=2){
        to_binary(num/2);
    }
    printf("%c",bin+'0');
}

int main(){
     int num = 10;
     to_binary(num);
     system("pause");
    return 0;
}

C中单个数字到字符的转换,加‘0’。


5. 顺序和逆序输出正整数的每一位

顺序输出:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void print_num(int num){

    if(num<10){
        printf("%d\n",num);
    }
    else{
        print_num(num/10);
        printf("%d\n",num%10);
    }
}

int main()
{
    int num=1234560;
    print_num(num);
    system("pause");        
}

逆序输出:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void print_num(int num){

    if(num<10){
        printf("%d\n",num);
    }
    else{
        printf("%d\n",num%10);
        print_num(num/10);
    }
}

int main()
{
    int num=1234560;
    print_num(num);
    system("pause");        
}


6. 求组成一个正整数的所有数字之和

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int sum_up(int n){
    if(n/10==0){
        return n;
    }
    return sum_up(n%10)+sum_up(n/10);
}

void main()
{
    int n=123456;
    printf("%d\n",sum_up(n));
    return;
}


7. 递归实现n^k

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int pow_fun(int n, int k){
    if(k==1){
        return n;
    }
    return n*pow_fun(n,k-1);
}

void main()
{
    int n=3,k=3;
    printf("%d\n",pow_fun(n,k));
    return;
}


8. 求两个正整数的最大公约数

也称最大公因子,指两个或多个整数共有约数中最大的一个。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int Max_common_divisor(int m, int n){
    if(m<=1||n<=1){
        return 1;
    }
    if(m>n){
        return Max_common_divisor(m-n,n);
    }
    if(m<n){
        return Max_common_divisor(n-m,m);
    }
    if(m=n){
        return n;
    }
}

void main()
{
    int m=64,n=76;
    printf("%d\n",Max_common_divisor(m,n));
    return;
}

另一种实现:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int gbs(int n,int m)
{
    if(n%m){
        return gbs(m,n%m);       
    }
    else{
        return m;
    }
}

void main()
{
    int m=8,n=12;
    printf("%d\n",gbs(m,n));
    return;
}


9. 求两个正整数的最小公倍数

两个或多个整数公有的倍数叫做它们的公倍数,其中除0以外最小的一个公倍数就叫做这几个整数的最小公倍数。
a,b的最小公倍数 =  a×b/(a,b的最大公约数)


10. 递归实现将字符串反向输出

void funN(char *s)
{    
    if (*s != NULL)
    {
        funN(s+1);
        printf("%c",*s);
    }    
}


11. 统计字符串中第一个空字符(或特定字符)前的字符长度

例如对于{'a','b','c','\0','d','e'},N=2、3时,长度是2、3,N=5、6时,长度是3。 思路: 字符串折半递归。

扫描二维码关注公众号,回复: 3962479 查看本文章
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int strlen_length(char* str,int N){
    int length;  //C中变量定义要放在最前
    if(*str=='\0' || N==0){
        return 0;
    }
    if(N==1)
    {
        return 1;
    }    
    length = strlen_length(str,N/2);
    if(length<N/2)  //这种情况表示length==N,说明前半段中没有空字符
    {
        return length;
    }
    else
    {
        return (length+strlen_length(str+N/2,(N+1)/2));
    }
}

int main()
{
    char str[] = {'a','b','\0','c'};
    printf("%d",strlen_length(str,2));
    system("pause");        
}


12. 不创建任何临时变量,实现strlen功能

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int strlen(char* str){
    if(*str=='\0'){
        return 0;
    }
    return(1+strlen(str+1));
}

int main()
{
    char *str="1234560";
    printf("%d",strlen(str));
    system("pause");        
}

13. 回文判断,如“abcdedbca”是回文

0和单个字符也认为是回文。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


int huiwen(char *str, int length){
    if(length<=1){
    return 1;
    }        
    if(*str==*(str+length-1)){
    return huiwen(str+1,length-2);
    }        
    else{
    return 0;
    }
}

int main(){
    char str[]="aaabcde66edcbaaa";
    printf("%d\n",huiwen(str,strlen(str)));
    system("pause");
    return 0;
}

14. 斐波那契数列

又称黄金分割数列、因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”。 斐波那契数列中F(n)=F(n-1)+F(n-2)(n>=3)。

递归实现,判断斐波那契数列中第n位的值。

#include<stdio.h>
#include<stdlib.h>

long bofei(int val)
{
    if(0>=val){
        return 0;
    }
    if(1==val){
        return 1;
    }
    if(2==val){
        return 2;
    }
    return bofei(val-1)+bofei(val-2);   
}

int main()
{   
    int ss = 10;
    
    printf("%ld",bofei(ss));
    return 0;
}


非递归实现,判断斐波那契数列中第n位的值:

#include<stdio.h>
#include<stdlib.h>

long bofei(int val)
{
    long arr[100];
    arr[0]=0;
    arr[1]=1;
    arr[2]=2;
    for(int i=3; i<=val;i++){
        arr[i]=arr[i-1]+arr[i-2];
    }
    return arr[val];   
}

int main()
{   
    int ss = 50;
    
    printf("%ld",bofei(ss));
    return 0;
}


15. 汉诺塔问题

A(from)、B(helper)、C(to)

1. n个盘从A移动到C,需要借助B,先把n-1个盘移动到B(这个最终呈现出来的效果,至于过程怎么实现的不管),再把第n的盘移动到C;
2. 再把B上的n-2个盘借助A,移动到A上,把第n-1的盘移动到C; 如此反复;

void hannoi(int n, char from, char helper, char to){
    if(n>1){
        hannoi(n-1,from,to,helper);
        print_line("take"+n+"from"+from+"to"+to);
        hannoi(n-1,helper,from,to)
    }
    else{
        print_line("take"+n+"from"+from+"to"+to);)
    }
}


16. 长度为n的、没有重复字符的字符串全排列,求全排列种类的数目。

思路:1. 先确定首位,首位有n种情况;    2. 确定首位之后,剩下的n-1位再全排列;    3. 全排列次数f(n)=n*f(n-1);
递归求法:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int permutation_num(int n){
        static int num=1;
        if(1>=n){
            return 1;
        }
        num=n*permutation_num(n-1);
        return num;
    }

void main()
{
    int n=6;
    printf("%d\n",permutation_num(n));
    return;
}


非递归求法:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int permutation_num(int n){
        int list_[n]; //list_[0]~list_[n-1]对应1~n位字符全排列的排列数
        list_[0] = 1;
        for(int i=1;i<n;i++){
            list_[i] = (i+1)*list_[i-1];
        }
        return list_[n-1];
    }


void main()
{
    int n=6;
    printf("%d\n",permutation_num(n));
    return;
}

17. 打印出一个字符串所有的全排列

如abc,全排列为abc、acb、bac、bca、cab和cba。
思路: 第一步是确定第一个位置的字符,就是第一个位置与后边的所有字符进行交换。这一共有n中情况,所以递归函数里涉及一个n次循环。
第二步,就是对除了第一个位置的后边所有位置的字符进行相同处理;直至剩下一个字符,打印;这里是递归函数里循环体。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

void permutation_num(char* start, char* move){

    if(*move=='\0')
    {
        printf("%s\n",start);
        return;
    }
    else
    {
        for(char* begin=move;*begin!='\0';begin++)
        {
            char temp = *begin;
            *begin = *move;
            *move = temp;
            permutation_num(start,move+1);
            temp = *begin;
            *begin = *move;
            *move = temp;     
        }
    }        
}

void main()
{
    char str[] = "abc";
    permutation_num(str,str);
    return;
}

以上递归没有考虑去重,去重版本:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int swap_(char * begin, char* end){
    for(char * start=begin; start!=end;start++){
        if(*start==*end){
            return 0;
        }
    }
    return 1;
}


void permutation_num(char* start, char* move){

    if(*move=='\0')
    {
        printf("%s\n",start);
        return;
    }
    else
    {
        for(char* begin=move;*begin!='\0';begin++)
        {
            if(swap_(move,begin)){
                char temp = *begin;
                *begin = *move;
                *move = temp;
                permutation_num(start,move+1);
                temp = *begin;
              *begin = *move;
            *move = temp;          
            }
        }
    }        
}

void main()
{
    char str[] = "acc";
    permutation_num(str,str);
    return;
}


18. 判断一系列字符串中是否有重复字符串

C中没有string字符串指针,需要使用二级指针实现。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int repetition(char** start){

    if(*(start+1)=='\0'||*(start)=='\0') //如果只有一个元素或为空
    {
        return 0;
    }
    else
    {
        for(char** begin=start+1;*begin!='\0';begin++)  //逐个比对
        {
            if(*start == *begin){
                return 1;
            }
        }
        repetition(start+1);
    }        
}

void main()
{
    char *str[]= {"aa","bb","cc","aa"};
    printf("%d\n",repetition(str));
    return;
}


19. 递归实现字符反转

1. 原地反转
2. 自己实现strlen功能

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int strlen_(char *str){
    if(*str=='\0'){
        return 0;
    }
    return 1+strlen_(str+1);
}

void reverse(char* p){    
    if(strlen_(p)<=1||*p=='\0'){
        return;
    }
    else{
        int length = strlen_(p);
        char temp = *p;
        *p = *(p+length-1);
        *(p+length-1) = '\0';    
        reverse(p+1);
        *(p+length-1) = temp;
    }  
}


void main()
{      
    char str[]="abcedfgd";
    reverse(str);    
    printf("%s\n",str);
    return;
}

20. 将一个正整数按字符格式输出,实现itoa功能

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

char* reverse(char* p){
    char* str=(char*)malloc(10);
    int length = strlen(p);
    for(int i=0;i<length;i++){
        str[i]=p[length-i-1];
    }
    str[length]='\0';
    return str;
}

char* itoa(int num)
{
    char* str = (char*)malloc(10);
    char* p = str;
    for(num;num>0;num = num/10){
        *p = (num%10)+'0';        
        p=p+1;        
    }
    *p='\0';    
    return reverse(str); //字符反转   
}


void main()
{      
    int num=123456;    
    printf("%s\n",itoa(num));
    return;
}


21. 将一个正整数按“千分位”格式化形式输出,从个位起,每三位加逗号,如1234567,变成1,234,567

相关:
1. 自己实现strlen
2. 正整数转字符串
3. 字符串反转
4. 字符串插入

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int strlen_(char *str){
    if(*str=='\0'){
        return 0;
    }
    return 1+strlen_(str+1);
}

void reverse(char* p){    
    if(strlen_(p)<=1||*p=='\0'){
        return;
    }
    else{
        int length = strlen_(p);
        char temp = *p;
        *p = *(p+length-1);
        *(p+length-1) = '\0';    
        reverse(p+1);
        *(p+length-1) = temp;
    }  
}

char* itoa(int num)
{
    char* str = (char*)malloc(10);
    char* p = str;
    for(num;num>0;num = num/10){
        *p = (num%10)+'0';        
        p=p+1;        
    }
    *p='\0';    
    reverse(str); //字符反转
    return str;   
}


char * insert_douhao(char* str){
    int length = strlen_(str);    
    char* p =(char*)malloc(length+abs(length-1)/3);   
    for(int i=0;i<length+abs(length-1)/3;i++){
        if((i-length%3)%4==0){
            *(p+i)=',';
        }
        else{
            *(p+i)=*(str++);
        }
    }   
    return p;
}

char* int_to_qianfenwei(int num){
    char* p = itoa(num);
    printf("%s\n",p);
    return insert_douhao(p);
}


void main()
{   
    int num = 1234567012;   
    printf("%s\n",int_to_qianfenwei(num));    
    return;
}

在递归里,对于指针p,一般忌讳使用 p++, 通常使用p+1 。 p++之后指针p的值已经变了,不再指向初始地址,而p+1只是传入指针p之后的那个地址,指针p本身并没有改变。

NULL、'\0'、0
NULL用于指针或者对象的置空,表示一个不指向任何对象的空指针。
'\0'用于字符串的结束标志。
0也可以作为字符串的结尾标志,如下表述也是没有问题的:
char str[4] = { '1', '2', '3', 0 };  //这里strlen(str)的值是3

C中单个数字到字符的转换,加‘0’。

猜你喜欢

转载自blog.csdn.net/dcrmg/article/details/83583288