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)=0
,F(1)=1
,F(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
上面的指针p
、q
指向的都是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
从上面的结果可以看出,b
与a
指向的并不是同一个空间,他们的地址并不相同,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并不受影响。
注意:代码中涉及到手动分配内存操作,一定要记得做释放内存!否则可能造成内存泄漏问题!