【C语言】二、递归、浅拷贝和深拷贝

1.递归

递归是指在函数内部调用自身的行为

递归函数必备两个要素:

  • 递归终止条件:函数必须在递归到某个深度结束,避免无限递归。相当于递归必须有一个出口来结束整个递归。
  • 递归调用:函数需要在内部调用自身,相当于递归的入口。

举例说明

1)阶乘

#include <stdio.h>

unsigned long long int Jc(unsigned int n){
    
    
    if(n<=1){
    
    
        return 1;
    }
    return n * Jc(n-1);
}
int main() {
    
    
    int a = 3;
    printf("%d的阶乘为:%llu\n", a, Jc(a));
    return 0;
}

输出:

3的阶乘为:6

上面是一个简单的递归函数实现计算阶乘的效果,当参数n小于等于1的时候终止递归,如果参数大于1,函数不断调用自身,并且n依次递减直到n小于等于1。下面对逐步对递归进行分析:

  • 首先我们在主函数调用了计算阶乘的函数Jc(3),进入函数首先判断3<=1,不满足条件
  • 返回3 * Jc(3-1),也就是进入Jc(2),判断2<=1,不满足条件
  • 返回2 * Jc(2-1),也就是进入Jc(1),判断1<=1,满足条件,返回值1
  • 2 * Jc(2-1)就等于2 * 1 Jc(2)返回值就是2
  • 3 * Jc(3-1)就等于3 * 2,Jc(3)返回值就是6
  • 然后回到第一层调用,函数执行结束并返回6

2)斐波那契数列

斐波那契数列是指这样一个数列:0、1、1、2、3、5、8、13、21、34、55、89、144……就是满足F(0)=0F(1)=1F(n) = F(n-1) + F(n-2)条件的数列,下面用程序计算斐波那契数列第n项的值:

// 斐波那契数列:0,1,1,2,3,5,8,13...每一项都等于前两项之和
unsigned long long int Fs(unsigned int n){
    
    
    if (n <= 1){
    
    
        return n;
    }
    return Fs(n-1) + Fs(n-2);
}
int main() {
    
    
    int b = 7;
    printf("斐波那契数列中第%d项为:%llu\n", b, Fs(b));
    return 0;
}

输出:

斐波那契数列中第7项为:13

2.浅拷贝

浅拷贝是指拷贝不同的指针指向同一块内存空间

#include <stdio.h>

int main() {
    
    
    int a = 10;
    int *p = &a;
    int *q = p;
    printf("p=%d,q=%d\n", *p, *q);
    *p = 5;
    printf("p=%d,q=%d\n", *p, *q);
    return 0;
}

输出:

p=10,q=10
p=5,q=5

上面的指针pq指向的都是a的地址,所以改变p的值,就相当于改变了a这个变量的内存空间的值,而q指针指向的也是a的内存空间,因此,q的值也会跟着改变,因为他们都是指向同一空间的指针,这种就称为浅拷贝。

3.深拷贝

深拷贝就是让不同的指针指向独立的内存空间

#include <stdio.h>

int main() {
    
    
    int a = 10;
    int b = a;
    printf("a的地址:%p,a的值:%d\n",&a,a);
    printf("b的地址:%p,b的值:%d\n",&b,b);
    return 0;
}

输出:

扫描二维码关注公众号,回复: 15825748 查看本文章
a的地址:000000000061FE1C,a的值:10
b的地址:000000000061FE18,b的值:10

从上面的结果可以看出,ba指向的并不是同一个空间,他们的地址并不相同,b属于是对a进行了深拷贝。如果a的值改变,并不会影响b的值。
下面我们实现一个字符串深拷贝的方法:

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


char *deepcopy_str(char *string) {
    
    
    int length = sizeof(strlen(string));
    char *str = (char *) malloc(length + 1); // 分配一块源字符串大小内存空间,+1是因为默认没有把'\0'算进去
    memmove(str, string, length + 1);
    return str;
}

int main() {
    
    
    char str1[100] = "Hello";
    char *str2;
    str2 = deepcopy_str(str1);
    printf("str1=%s,str2=%s\n", str1, str2);
    printf("请输入str1的值:\n");
    scanf("%s",str1);
    printf("str1=%s,str2=%s\n", str1, str2);
    free(str2); // 释放str2指向的空间
    str2 = NULL; // 释放指针str2
    return 0;
}

输出结果:

str1=Hello,str2=Hello
请输入str1的值:
World
str1=World,str2=Hello

从上面的结果可以清楚的看到,我们实现了字符串的深拷贝操作,当字符串str1改变的时候,str2并不受影响。

注意:代码中涉及到手动分配内存操作,一定要记得做释放内存!否则可能造成内存泄漏问题!

猜你喜欢

转载自blog.csdn.net/m0_56963884/article/details/129299940