一、递归:函数自己调用自己
1.Fibon数列是使用递归最差的例子
//Age(5)表示第5个人的年龄
//Age(4)表达第4个人的年龄
//Age(3)表达第3个人的年龄
//Age(2)表达第2个人的年龄
//Age(1)表达第1个人的年龄
//Age(n)表达第n个人的年龄
//Age(n-1)表达第n-1个人的年龄
int Age(int n)// 时间复杂度:O(n) 空间复杂度:O(n)
{
int tmp =10;
if(n == 1)//边界值
{
return 10;
}
else
{
tmp = Age(n-1) +2;//前进段
return tmp;
}
}
int Age1(int n)// 时间复杂度:O(n) 空间复杂度:O(1) (tmp与n无关)
{
int tmp = 10;
for(int i=1;i<n;i++)
{
tmp += 2;
}
return tmp;
}
//1+...+n
//Sum()
int Sum(int n)//递归实现, 时间复杂度:O(n) 空间复杂度:O(n)
{
if(n <= 1)
{
return n;
}//Sum(n) = Sum(n-1) + n;
else return Sum(n-1) + n;
}
//n!=(n-1)!*n
int Fac(int n)
{
if(n==0 || n==1)
{
return 1;
}
else
{
return Fac(n-1) *n;
}
}
//Fibon(0) = 1
//Fibon(1) = 1;
//Fibon(n) = Fibon(n-1) + Fibon(n-2);
int Fibon(int n)//使用递归最失败的例子
{//O(2^n)
if(n==0 || n==1) //边界条件
return 1;
else
return Fibon(n-1) + Fibon(n-2);
}
//递归
//边界条件,返回段
int main()
{
printf("%d\n",Fibon(40));
//printf("%d\n",Sum(10));
//printf("%d\n",Sum(100));
//栈,大小1M,后进先出,由系统管理内存,局部变量存储在栈中
//char arr[1024*1000];
//printf("%d\n",Age1(50000));
/*printf("%d\n",Age(4));
printf("%d\n",Age(3));
printf("%d\n",Age(2));
printf("%d\n",Age(1));*/
return 0;
}
2.汉罗塔是使用递归最成功的例子
void Move(char x,char y)//模拟一个盘子的移动
{
count++;
printf("%c->%c\n",x,y);
}
{
count++;
printf("%c->%c\n",x,y);
}
void Hanio(int n,char a,char b,char c)
{
if(n== 1)
{
Move(a,c);
}
else
{
Hanio(n-1,a,c,b); //将最上面的盘子从a通过c移到b
Move(a,c);
Hanio(n-1,b,a,c); //将最上面的盘子从b通过a移到c
}
}
{
if(n== 1)
{
Move(a,c);
}
else
{
Hanio(n-1,a,c,b); //将最上面的盘子从a通过c移到b
Move(a,c);
Hanio(n-1,b,a,c); //将最上面的盘子从b通过a移到c
}
}
int main()
{
Hanio(10,'A','B','C');
printf("%d\n",count);
{
Hanio(10,'A','B','C');
printf("%d\n",count);
return 0;
}
}
二、时间复杂度
1、含义:执行的次数和问题规模之间的函数关系,不需要精确计算
2、只考虑高阶项,低阶项直接丢弃
3、系数不要
4、代码
(1)j与n相关 (3) n =10; //2条语句
for(i = 0;j<n;i++) n = 1000; //2条语句
{ n = 10000; //2条语句
count++; 2*1 = O(1)
for(j = 0;j < n;j++)
tmp += i;
}
(2)j与i相关
for(i = 0;j<n;i++)
{
count++;
for(j = 0;j < i;j++)
tmp += i;
}
j与n相关与j与i相关没有区别,时间复杂度一样
三、空间复杂度
1、含义:实现该算法,需要的额外辅助空间与问题规模间的函数关系。
2、额外辅助空间的变量/结果与n相关:O(n),与n无关:O(1) (不一定)
四、递归的时间复杂度
(1)int Fibon1(int n)//O(n)
{
int f1 = 1;
int f2 = 1;
int f3 = 1;
for(int i=1;i<n;i++)
{
f3 = f1 + f2;
f1 = f2;
f2 = f3;
}
return f3;
}
(2)void Fun(int n) //O(n)
{
if(n<1)
return 1;
else
return Fun(n-2)+1;
}
(3)void Fun(int n) //O(log2n)
{
if(n<1)
return 1;
else
return Fun(n/2)+1;
}
n,n/2,n/4,n/8...1
1,2,4,8...n
假设走了x次
2^x = n x = logg2n
(4)O(log2n)与O(n)比较,O(log2n)效率高
n 1000 1000000
O(n) 50次 500000次
O(log2n) 10次 20次
(4)int arr[10] = {1,2,3,4,5,6,7,8,9}; int brr[3][4];
类型 类型
arr int *p brr int (*p)[4]
arr int *p brr int (*p)[4]
arr+1 int *p brr+1 int (*p)[4](第二个)
arr[0] int brr[0] int *p
arr[0]+1 int brr[0]+1 int *p
brr[0][0] int
五、一些小知识
1、栈 stack 后进先出 典型应用:撤销(文件也可以撤销)
所有的局部变量都在栈里,由系统管理内存,系统可自己回收内存
缺点:内存不大“1024*1000Bytes = 1M
2、标记法:用筛选法找素数