郝斌版《数据结构》学习笔记
时间:2015.08.31 - 2015.09.05
函数调用前系统准备三件事:
1、将所有的实际参数,返回地址等信息传递给被调函数予以保存;
2、被调函数的局部变量(也包括形参)分配存储区;
3、将控制转移到被调函数的入口。
被调函数返回给调用函数前,系统完成三件事:
1、保存被调函数的计算结果;
2、释放被调函数的数据区;
3、依照被调函数保存的返回值地址,将控制权限转移给调用函数
多个函数调用时,后调用先返回
上述函数之间的传递及控制转移必须借助栈来实现。
调用函数时,在栈顶分配存储区;退出时,释放存储区。
当前正在运行的函数的数据区必须在栈顶。
调用10次,只分配一次代码空间
递归要满足的三个条件:
1、递归必须有一个明确的终止条件;
2、该函数所处理的数据规模必须在递减或递增;
3、这个转化必须是可解的。
循环和递归的区别:
递归:易于理解,速度慢,存储空间大(调用,发送地址、实参,花费时间)
循环:不易理解,速度快,存储空间小
递归的应用:
1、树和森林就是以递归的方式定义的
2、树和图的很多算法以递归来实现
3、数学公式
菲波拉契数列:1 2 3 5 8 13 21 34(当前数是前两位数之和)
简单例子(不同函数间的互相调用)
# include <stdio.h>
void f();
void g();
void k();
void f()
{
printf("FFFF\n");
g();
printf("1111\n");
}
void g()
{
printf("GGGG\n");
k();
printf("2222\n");
}
void k()
{
printf("KKKK\n");
}
int main(void)
{
f();
return 0;
}
自我调用
# include <stdio.h>
/*
void f()
{
printf("FFFF\n");
f(); //溢栈时出错
}
*/
void f(int n)
{
if(n == 1)
printf("FFFF\n");
else
f(n-1);
}
int main(void)
{
f(3);
return 0;
}
间接调用
# include <stdio.h>
int f(int n)
{
n += 2;
return n;
}
int main(void)
{
int val;
val = f(5);
printf("val = %d\n", val);
return 0;
}
递归实例1 - 阶乘
1、求阶乘
方法一:循环
# include <stdio.h>
int main(void)
{
int val;
int i;
int mult = 1;
printf("pls input a number: ");
printf("val= ");
scanf("%d", &val);
for (i=1; i<=val; ++i)
mult = mult * i;
printf("%d的阶乘是:%d!= %d\n", val, val, mult);
return 0;
}
方法二:递归
# include <stdio.h>
long f(long n)
{
if (1 == n)
return 1;
else
return f(n-1) * n;
}
int main(void)
{
int val;
printf("pls intput a num: val = ");
scanf("%d", &val);
printf("%d的阶乘是:%d!= %ld\n", val, val, f(val));
return 0;
}
递归求阶和
# include <stdio.h>
long sum(long n)
{
if (1 == n)
return 1;
else
return sum(n-1) + n;
}
int main(void)
{
int val;
printf("pls intput a num: val = ");
scanf("%d", &val);
printf("%d的阶和是:%d!= %ld\n", val, val, sum(val));
return 0;
}
递归实例2 - 汉诺塔
# include <stdio.h>
void hannuota(int n, char A, char B, char C)
{
/*
如果是1个盘子
直接A移到C
否则
将A上的n-1个盘子借助C移动到B
将A上的第n个盘子移到C
将B上面的n-1个盘子借助A移到C
*/
if (1 == n)
{
printf("将编号为%d的盘子直接从%c柱子移到%c柱子\n", n, A, C);
}
else
{
hannuota(n-1, A, C, B);
printf("将编号为%d的盘子直接从%c柱子移到%c柱子\n", n, A, C);
hannuota(n-1, B, A, C);
}
}
int main(void)
{
char ch1 = 'A';
char ch2 = 'B';
char ch3 = 'C';
int n;
printf("请输入要移动盘子的个数:");
scanf("%d", &n);
hannuota(n, 'A', 'B', 'C');
return 0;
}