鹏哥C语言复习——函数递归

使用递归时有两条必须要满足的条件:

1.存在限制条件,当满足这个限制条件的时候,递归便不再继续

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

例1.

输入1234,要求打印1 2 3 4(数字与数字间有空格)。

void print(unsigned int n)
{
    if(n>9)  //递归限制条件
    {
        print(n/10);
    }
    printf("%d,n%10);
}


int main()
{
    unsigned int num = 0;
    scanf("%u", &num);
    print(num);
    return 0;
}

递归代码解释:

num为1234,传给了print函数,故n为1234,比9要大,1234/10 = 123,即把123传输给了print函数(此时printf由于在递归操作之后,所以先不执行该语句);以此类推,123比9大,所以继续“/10”的操作,传给print函数;直至n为1,跳出if语句,printf了1这个值,在n为12的这一情况下的if语句执行结束,往后执行printf(12%10),即打印了2,然后又回到了n为123的这种情况,以此类推,最后成功打印1 2 3 4。 

详细讲解请查看本视频19分48秒处:鹏哥C语言视频讲解

假设不存在if语句的这一限制条件,会出现栈溢出(每一次函数的调用都会在栈区申请空间,当递归无数次,函数调用无数次,出现栈溢出),这种情况称为死递归。

例2.

不允许使用库函数strlen,同时编写函数不允许创建临时变量,求字符串"abc"的长度。(模拟实现strlen函数)

void my_strlen(char *str)
{
    if(*str != '\0')
        return 1 + my_strlen(str+1);
    else
        return 0;
}

int main()
{
    char arr[] = "abc";
    int len = my_strlen(arr);
    printf("%d",len);
    return 0;
}

递归代码解释:

在传参时,传入的是arr数组首地址,即'a'。

//0+ my_strlen("a")

//0+1+ my_strlen("b")

//0+1+1+ my_strlen("c")

//0+1+1+1+ my_strlen("\0")

//0+1+1+1+0 = 3

//len = 3,str == '\0'时,返回0数值给my_strlen("c")函数,以此类推,形成递归。

例3.

在不使用库函数strlen的情况下,编写一个函数reverse_string(char *string)递归实现字符串逆序

注:是将string这一字符串逆序排列,而不是逆序打印string这一字符串;同时本题除递归外也可以使用函数迭代或者直接在main函数里进行循环

为本例子讲解方便,假设string[ ] = "abcdef"

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


void reverse(char *str)
{
    char tmp = *str;
    int len = my_strlen(str);
    *str = *(str+len-1);
    *(str+len-1) = '\0';
    if(my_strlen(str+1)>=2)
        reverse(str+1);
    *(str+len-1) = tmp;
}

int main()
{
    char arr[] = "abcdefg";
    reverse(arr);
    printf("%s\n",arr);
    return 0;
}

递归代码解释:

自定义函数实现strlen函数功能已在上文提过,此处省略,并且本例用的是函数迭代的方法

//reverse("abcdefg")

//a和g交换加上reverse("bcdef")

//b和f交换加上reverse("cde")

//c和e交换加上reverse("d")

//例如a和g交换,具体方法是先把a拿出来存入临时变量tmp,然后把g放在字符串首,再把g的位置变成\0(字符串结束标志),现在剩下"gbcdef",把他当中的g和f用同样的方法交换后,然后再把\0赋值成a

//b和f用相似方法,将f放在字符串第二位,然后把b拿出来存入临时变量tmp,再把f变成\0,现在剩下"gfcde"(全部写出来应该是"gfcde\0a",由于字符串中的\0以后的所有字符都不会算在字符串中,所以剩下"gfcde")

tips:字符串可以看成由多个字符组成的数组,数组传参时传的是数组首地址,数组是一个指针常量,所以自定义函数在接收时可以使用指针来接收,所以在自定义函数中指针的用法和数组相似。这些内容将会在以后找机会深度讲解,这里笔者先一笔带过了。

注:所有例子都没库函数,三个例子需要加上stdio.h。

笔者在看完鹏哥C语言之后,把leetcode上简单难度的递归题(无链表,绝对不是因为笔者没学过链表)做完了,下面是汇总

1. leetcode第二百三十一题:2的幂(C语言)

2. leetcode第五百零九题:斐波那契数(C语言)

3. leetcodeLCR 187题:破冰游戏(C语言+约瑟夫环)

4.在写了,在写了(之后会传,笔者在下学期学完数据结构后会将链表相关递归题一同上传)

写在最后:B站up“鹏哥C语言”的视频讲解层层递进,抽丝剥茧,真的很不错。推荐一下~

你可能感兴趣的:(c语言,开发语言)