递归:函数的嵌套
函数递归的定义
程序调用自身的编程技巧称为递归( recursion)。
递归做为一种算法在程序设计语言中广泛应用。 一个过程或函数在其定义或说明中有直接或间接
调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解。
函数递归的两个必要条件
存在限制条件,当满足这个限制条件的时候,递归便不再继续。
每次递归调用之后越来越接近这个限制条件。
错误用法:
int sum(int n)
{
return sum(n-1)+n;//这里没有限制条件,或者说一直调用函数sum,最终没有确切的值返回
}
int main()
{
int n,y;
scanf("%d",&n);
y=sum(n);
printf("y = %d\n",y);
return 0;
}
递归函数举例
1.实现n的阶乘,并输出!
int jiec(int n)
{
if(n==1)//结束条件
{
return 1;
}
else
{
return jiec(n-1)*n;//调用递归函数
}
}
int main()
{
int n,y;
scanf("%d",&n);
y=jiec(n);//调用函数jiec
printf("y = %d\n",y);
return 0;
}
2.汉诺塔
需求;
有一个老和尚想把64个盘子从A座移动到C座,
但每次只允许移动一个盘,且在移动过程中3个座上都始终保持大盘在下,小盘在上。在移动过程中可以利用B座。
思路:
问题n
|--问题n-1 与 n
|--问题n-2
|---
...结束条件
hanoi(64)
|---hanoi(63)
|---hanoi(62)
|---
...
hanoi(1)//A-->C
也就是说:可以看成:在还有64个盘子时,开始柱为'A',辅助柱'B',目标柱'C'
要挪64个盘子,就先把63个移到B,此时A剩下1个(最大的),把这个盘子从A移到C。然后还有63个盘子,此时起始柱为B,然后辅助柱为A,目标柱为C。此时要把63个盘子移到C,就需要先把上面62个移到A,然后再把B上第63个盘子移到C。依次类推!
代码展示:
#include <stdio.h>
void move(int n ,int pole1,int pole2)
{
static int step = 1;
printf("%03d:[disk %d] : %c --> %c\n",step++,n,pole1,pole2);
}
//起始柱 辅助柱 目标柱
void hanoi(int n, int A, int B, int C)
{
if (1==n)
{
move(n,A,C);
}else
{
hanoi(n-1,A,C,B);//n-1 先挪走
puts("-------");
move(n,A,C); // 将第n个 挪到 目标柱
puts("-------");
hanoi(n-1,B,A,C);
}
}
//n = 3;
//hanoi(2,'A','C','B')
// | --------------------> hanoi(1,'A','B','C')
// move(2,'A','B'); [2:A->B]
// |----------------------->move(1,'A','C') [1:A->C]
//move(3,'A','C'); -----> [3:A->C]
//hanoi(2,'B','A','C');
int main(void)
{
int n = 0;
printf("Input numbers of disk: ");
scanf("%d",&n);
hanoi(n,'A','B','C');
return 0;
}
内存结构:
栈:
1.是一种数据结构,FILO(First Input Last Output)先进后出
2.内存上的一块空间
3.大小有限,
4.存放函数的参数值,局部变量的值等
5.自动申请,自动释放
32位,4MB的栈内存空间
64位,8MB的栈空间。
2^32-->2^10 * 2^10 * 2^10 *2*2
1024 1024 1024
1K 1M 1G
堆:
1.空间很大
2.手动申请,手动释放(还没看到)
字符串常量区:
"hello" //字符串常量
不能被修改 - 只读
全局区:
存放全局变量和静态变量
代码区:
存放代码
程序 = 数据 + 代码