第十一讲函数的递归调用及函数中的变量定义
一、函数的递归调用
1.递归的概念
直接递归调用:调用函数的过程中又调用该函数本身,自己调用自己。
间接递归调用:调用f1函数的过程中调用f2函数,而f2中又需要调用f1。
以上均为无终止递归调用。为了让这种调用终止,一般要用if语句来控制使递归过程到某一条件满足时结束。
2、递归法
类似于数学证明中的反推法,从后一结果与前一结果的关系中寻找其规律性。
递归法:从结果出发,归纳出后一结果与前一结果直到初值为止存在的关系
编程思想:设计一个函数(递归函数),这个函数不断使用下一级值调用自身,直到结果已知处——选择控制结构
其一般形式是:
递归函数名f (参数n)
{ if (n=初值)
结果=常量;
else
结果=含f(x-1)的表达式;
return 结果;
}
例1.输入一个n,编写函数求n!,根据不同的算法,我们可以用三种方式。
方式一:用递推算法,Sn=n!的递推关系如下:
1 (n=1,0)
Sn=
Sn-1×n n>1
是一种累计乘积的关系,先得到上一个数的阶乘,然后再得到得到下个数的阶乘,用循环结构来实现。
程序代码如下:
main()
{ int n;
float sn;
float fac(int ); /*函数的声明*/
printf("Input n=");
scanf("%d",&n);
sn=fac(n); /*函数的调用*/
printf("%d!=%.0f",n,sn);
}
float fac(int n) /*函数的定义*/
{ float f=1.0;
int i;
if (n==0||n==1) return f;
for(i=1;i<=n;i++)
f=f*i;
return f;
}
方式二:用递归算法,f(n)=n!的递归求解关系如下:
1 (n=1,0)
f(n)=
f(n-1)×n n>1
递归程序分两个阶段执行——
①回推(调用):欲求n! →先求 (n-1)! →(n-2)! →…→ 1!
若1!已知,回推结束。
②递推(回代):知道1!→2!可求出→3!→…→ n!
注意:在此可画图来说明
程序清单如下:
main()
{ int n;
float sn;
float fac(); /*函数的声明*/
clrscr();
printf("Input n=");
scanf("%d",&n);
sn=fac(n); /*函数的调用*/
printf("%d!=%.0f",n,sn);
}
float fac(int n) /*函数的定义*/
{ float f;
if (n==0||n==1) f=1;
else f=fac(n-1)*n;
return f;
}
方法三:在函数中定义静态变量来实现,一般说来,在任何函数中,我们都可以定义变量:float f;而这种定义默认为f为自动变量atuo,当函数调用结束的时候,该变量的存储空间被释放,也就是说变量f不复存在。但如果我们在定义变量的时候,声明是静态变量:static float f;f的值在函数调用结束以后,占用的存储空间不被释放,下次调用时候,其初值就是上次调用结束的值,利用这一特性,我们可以用来解决阶乘的问题。
main()
{ int n,i;
float fac(); /*函数的声明*/
printf("Input n=");
scanf("%d",&n);
for(i=1; i<=n;i++) /*函数的循环调用*/
printf(“%d!=%f\n”,i,fac(i));
}
float fac(int n) /*函数的定义*/
{ static float f=1;
if n>0
f=f*n;
return f;
}
例2 在屏幕上显示杨辉三角形,行数由用户输入。
分析:若起始行为第1行,则:第x行有x个值,对第x行第y列,
其值(不计左侧空格时)为以下递归关系:
1 (y=1|| y=x)
c(x,y)=
c(x-1,y-1)+c(x-1,y)
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
………………
程序如下:
main(){
int i,j,n;
printf("Input n=");
scanf("%d",&n);
for (i=1;i<=n;i++)
{ for (j=0;j<=n-i;j++)
printf(" "); /*为了保持三角形态,此处输出两个空格*/
for (j=1;j<=i;j++)
printf("%3d ",c(i,j));
printf("\n");
}
}
int c(int x,int y)
{int z;
if (y==1||y==x) return 1;
else
{ z=c(x-1,y-1)+c(x-1,y);
return z;
}
}
作业题1:用递归算法计算Fibonacci数列问题。输入一个n,输出前n 项的和
1 (n=1)
提示:fib(n)= 1 (n=2)
fib(n-1)+fib(n-2) (n>1)
例三.运行下列程序,当输入字符序列AB$CDE并回车时,程序的输出结果是什么?
#include
void rev()
{ char c;
c=getchar();
if (c=='$') printf("%c",c);
else
{ rev();
printf("%c",c);
}
}
main()
{
rev();
}
结果:$BA
思考题目:输入一个整数,将其转换为字符输出。。
二、变量的存储类别
存储类别:
●register型(寄存器型)
变量值存放在运算器的寄存器中——存取速度快,一般只允许2-3个,且限于char型和int型,通常用于循环变量(在微机的Turbo C中实际上自动转为auto型)。
●auto型(自动变量型)
变量值存放在主存储器的动态存储区(堆栈方式)。
优点——同一内存区可被不同变量反复使用
在函数中定义以上两个类型的变量以后,只能属于该函数,函数的调用结束时,变量的存储空间便被释放,不能被保存下来。下次调用时,又给
变量重新分配存储空间。
●static型(静态变量型)
变量值存放在主存储器的静态存储区,程序执行开始至结束,始终占用该存储空间,但在某个函数中定义的,也只能在该函数中有效,不能被其他的模块所访问。
●extern型(外部变量型)
同上,但作用范围大大拓宽,可以被其他模块和函数所访问。
以上两种均属于“静态存储”性质,即从变量定义处开始,在整个程序执行期间其值都存在。
未说明存储类别时,函数内定义的变量为auto型,函数外定义的变量为extern型。
例四、分析下列程序的输出:
f(int a)
{b=0;
static c=3;
b=b+1;
c=c+1;
return a+b+c;
}
main()
{int a=2,i;
for(i=0;i<3;i++)
printf(“%6d”,f(a));
}
三、局部变量和全局变量
1、局部变量——函数内部或复合语句内定义的变量
auto(默认)所在函数调用结束时,其值自动消失
局部变量 register 如不赋初值,取不确定值为初值
static 所有函数调用结束,其值仍保留(如不赋初值,取
初值为0(数值型)或空格(字符型)约定:所有形参都是局部变量,局部变量只在本函数或本复合语句内才能使用,在此之外不能使用(视为不存在)——main函数也不例外。
2、全局变量——在函数之外定义的变量
extern(默认)允许本源文件中其他函数及其他源文件使用
全局变量
static 只限本源文件中使用,在定义的函数内有效
有效作用范围:从定义变量位置开始直到本源文件结束
如果需要将全局变量的作用范围扩展至整个源文件——
法1:全部在源文件开头处定义
法2:在引用函数内,用extern说明
法3:在源文件开头处,用extern说明
如果要将全局变量作用范围扩展到其他源文件,只需在使用这些变量的文件中对变量用extern加以说明。
【注意】
1.所有全局变量加不加static,都属于静态存储,如不赋初值,取初值为0(数值型)或空格(字符型)(注意与函数内部定义的static型局部变量的区别)
2.如果在同一个源文件中,全局变量与局部变量同名,则在局部变量作用范围内,全局变量不起作用。
例五、分析下列程序的结果:
【1】求程序运行结果
int a=3,b=5;
max(int a,int b)
{ int c;
c=a>b?a:b;
return c;
}
main()
{ int a=8;
printf("%d\n",max(a,b));
}
结果:8
【讨论】如果主函数中没有int a=8,结果?(5)
如果让主函数中int a=4或a=-1,结果?(均为5)
【2】求程序运行结果
void num()
{ extern int x,y;
int a=15,b=10;
x=a-b;
y=a+b;
}
int x,y;
main()
{ int a=7,b=5;
x=a+b;
y=a-b;
num();
printf("%d,%d\n",x,y);
}
结果:5,25
【讨论】如果第二行不加上extern呢?(12,2)
【3】求程序运行结果
int a;
fun(int i)
{ a+=2*i;
return a; }
main(){
int a=10;
printf("%d,%d\n",fun(a),a);
}
结果:20,10
【4】求程序运行结果
int i=0;
main()
{ int i=5;
clrscr();
reset(i/2); printf("i=%d\n",i); /*此处i为局部变量值,即i=5*/ reset(i=i/2); printf("i=%d\n",i); /*局部变量i=i/2,即i=2*/ reset(i/2); printf("i=%d\n",i);/*局部变量i的值未变*/ workover(i); printf("i=%d\n",i); /*局部变量i的值未变*/
}
workover(int i)
{ i=(i%i)*((i*i)/(2*i)+4);
printf("i=%d\n",i);
return i;
}
reset(int i) /*此处形参i使用主函数中局部变量i的值*/
{ i=i<=2?5:0; /*此处i为全部变量*/
printf("i1=%d ",i);
return i;
}
结果:i1=5 i=5
i1=5 i=2
i1=5 i=2
i=0
i=2
【讨论】如果将主函数中第二个reset(i/2)改为reset(i=3)
结果:1=5 i=5
i1=5 i=2
i1=0 i=3
i=0
i=3
函数的概念学案 学习目标 1、通过丰富实例,进一步体会函数是描述变量之间的依赖关系的重要数学模型,在此基础上学习用集合与对应的语言来刻画函数,体会对应关系在刻画函数概念中的作用 2、了解构成函数的要素,进一步巩固初中常见函数(一次函数、二次函数、反比例函数)的图像、定义域、值域 3、理解区间的概念,能准确地利用区间表示数集 4、通过从实际问题中抽象概括函数概念的活动,培养抽象概括能力 教学重点体会函数是描述变量之间的依赖关系的重要数学模型,正确理解函数的概念 教学难点函数的概念、符号y=f(x)的理解、 教学流程 一、问题1、在初中,甚至在小学我们就接触过函数,在实际生产生活中,函数也发挥着重要的作用,那么,请大家举出以前学习过的几个具体的函数 问题2、请大家用自己的语言来描述一下函数 二、结合刚才的问题,阅读课本实例(1)、(2)、(3),进一步体会函数的概念问题3、在实例(1)、(2)中是怎样描述变量之间的关系的?你能仿照描述一下实例(3)中恩格尔系数和时间(年)之间的关系吗? 问题4、分析、归纳上述三个实例,对变量之间的关系的描述有什么共同点呢? 函数的概念 一般地,设、是,如果按照某种确定的对应关系,使对于集合中的一个数,在集合中都有和它对应,那么就称为从集合到集合的一个函数,记作其中叫做自变量,的取值范围叫做函数的;与的值相对应的值叫做函数值,函数值的集合叫做函数的 问题5、在实例(2)中,按照图中的曲线,从集合B到集合A能不能构成一个函数呢?请说明理由 练习1、 1、在下列从集合到集合的对应关系中,不可以确定是的函数的是()(1),对应关系 (2),对应关系 (3),对应关系 (4),对应关系 2、下图中,可表示函数的图像只能是() 三、区间的概念
19.1.1《变量与函数》教学反思 本节课是八年级学生初步接触函数的入门课,必须让学生准确认识变量与常量的特征,初步感受现实世界各种变量之间相互联系的复杂性,同时感受到数学研究方法的化繁为简,知道在初中阶段主要研究两个变量之间的特殊对应关系。 函数定义的关键词是:“两个变量”、“唯一确定”、“与其对应”;函数的要点是:1 有两个变量,2 一个变量的值随另一个变量的值的变化而变化,3 一个变量的值确定另一个变量总有唯一确定的值与其对应;函数的实质是:两个变量之间的对应关系;学习函数的意义是:用运动变化的观念观察事物。与学习进行仔细的研究,有助于函数意义的理解,但是,不可能在一课的学时内真正理解函数的意义,继续布置作业:每个同学列举出几个反映函数关系的实例,培育学生用函数的观念看待现实世界,最后,我还说明了,函数的学习,是我们数学认识的第二个飞跃,代数式的学习,是数学认识的第一次飞跃:由具体的数、孤立的数到一般的具有普遍意义的数,函数的学习,是由静止的不变的数到运动变化的数。 在函数概念的教学中,应突出“变化”的思想和“对应”的思想。从概念的起源来看,函数是随着数学研究事物的运动、变化而出现的,他刻画了客观世界事物间的动态变化和相互依存的关系,这种关系反映了运动变化过程中的两个变量之间的制约关系。因此,变化是函数概念产生的源头,是制约概念学习的关节点,同时也是概念教学的一个重要突破口。教师可以通过大量的典型实例,让学生反复观察、反复比较、反复分析每个具体问题的量与量之间的变化关系,把静止的表达式看动态的变化过程,让他们从原来的常量、代数式、方程式和算式的静态的关系中,逐步过渡到变量、函数这些表示量与量之间的动态的关系上,使学生的认识实现 为了快速明了的引出课题,课前让学生收集一些变化的实例,从学生的生活入手,开门见山,来指明本节课的学习内容。本课的引例较为丰富,但有些内容学生解决较为困难,于是我采取了三种不同的提问方式:1.教师问,学生答; 2.学生自主回答; 3.学生合作交流回答。为了较好的突出重点突破难点,在处理教学活动过程中,让学生思考每个变化活动中反映的是哪个量随哪个量的变化而变化,并提出一个量确定时另一个量是否唯一确定的问题,在得出变量和常量概念的同时渗透函数的概念.为了更好的让学生理解变量和常量的意义,由“问题中分别涉及哪些量?哪些量是变化的,哪些量是始终不变的?”一系列问题,在借助生活实例回答的过程中,归纳总结出变量与常量的概念,并能指出具体问题中的变量与常量。函数的概念是把学生由常量数学的学习引入变量数学的学习的过程,学生初步接触函数的概念,难以理解定义中“唯一确定”的准确含义,我设置了以下二个问题:1.在前面研究的每个问题中,都出现了几个变量?它们之间是相互影响,相互制约的。2.在二个变量中,一个量在变化的过程中每取一个值,另一个量有多少个值与它对应?来理解具体实例中二个变量的特殊对应关系,初步理解函数的概念。为了进一步让学生理解“唯一对应”关系,借助函数图像,使学生直观的感受二个变量之间特殊对应关系-----唯一对应。通过这种从实际问题出发的探究方式,使学生体验从具体到抽象的认识过程,及时给出函数的定义。再从抽象转化到实际应用中去,加深学生对函数概念的理解。为了加强学生辨析函数的能力,我准备了一道思考题,Y2=X中对于X的每一个值Y都
递归调用详解,分析递归调用的详细过程 2009年05月23日星期六 22:52 一、栈 在说函数递归的时候,顺便说一下栈的概念。 栈是一个后进先出的压入(push)和弹出(pop)式数据结构。在程序运行时,系统每次向栈中压入一个对象,然后栈指针向下移动一个位置。当系统从栈中弹出一个对象时,最近进栈的对象将被弹出。然后栈指针向上移动一个位置。程序员经常利用栈这种数据结构来处理那些最适合用后进先出逻辑来描述的编程问题。这里讨论的程序中的栈在每个程序中都是存在的,它不需要程序员编写代码去维护,而是由运行是系统自动处理。所谓的系统自动维护,实际上就是编译器所产生的程序代码。尽管在源代码中看不到它们,但程序员应该对此有所了解。 再来看看程序中的栈是如何工作的。当一个函数(调用者)调用另一个函数(被调用者)时,运行时系统将把调用者的所有实参和返回地址压入到栈中,栈指针将移到合适的位置来容纳这些数据。最后进栈的是调用者的返回地址。当被调用者开始执行时,系统把被调用者的自变量压入到栈中,并把栈指针再向下移,以保证有足够的空间存储被调用者声明的所有自变量。当调用者把实参压入栈后,被调用者就在栈中以自变量的形式建立了形参。被调用者内部的其他自变量也是存放在栈中的。由于这些进栈操作,栈指针已经移动所有这些局部变量之下。但是被调用者记录了它刚开始执行时的初始栈指针,以他为参考,用正或负的偏移值来访问栈中的变量。当被调用者准备返回时,系统弹出栈中所有的自变量,这时栈指针移动了被调用者刚开始执行时的位置。接着被调用者返回,系统从栈中弹出返回地址,调用者就可以继续执行了。当调用者继续执行时,系统还将从栈中弹出调用者的实参,于是栈指针回到了调用发生前的位置。 可能刚开始学的人看不太懂上面的讲解,栈涉及到指针问题,具体可以看看一些数据结构的书。要想学好编程语言,数据结构是一定要学的。 二、递归 递归,是函数实现的一个很重要的环节,很多程序中都或多或少的使用了递归函数。递归的意思就是函数自己调用自己本身,或者在自己函数调用的下级
18.1变量与函数学案 Ⅰ、教学目标 1、知识与技能目标: 运用丰富的实例,使学生从具体的问题情境中了解常量与变量的含义,能分清实例中的常量与变量,领悟函数的概念,了解自变量与函数的意义。 2、过程与方法目标: 通过动手实践与探索,让学生参与变量的发现与函数的形成过程,感受获取知识的成功体验,提高学生分析问题和解决问题的能力。 3、情感态度价值观目标: 在引导学生探索实际问题的数量关系中,培养学生学习数学的兴趣并积极参与数学活动的热情,在解决问题的过程中体会数学的应用价值。 Ⅱ、教学重点 了解常量与变量的意义;理解函数概念和自变量的意义;确定函数关系式。Ⅲ、教学难点 函数概念的理解;函数关系式的确定 Ⅳ、教学过程 一、自主探究 (一)提出问题,创设情景 问题一:汽车以 60 千米/时的速度匀速行驶,行驶路程为 s 千米,行驶时间为 t 小时。 问题二:电影票的售价为10元∕张。第一场售出150张票,第二场场售出205张票,第三场场售出310张票,三场电影的票房收入各多少元?设一场电影售票x 张,票房收入y元.?怎样用含x的式子表示y ? 问题三:你见过水中涟漪吗?圆形水波慢慢地扩大,在这一过程中,当圆的半径r 分别为 10 cm,20 cm,30 cm 时,圆的面积S 分别为多少?S的值随r的变化而变化吗? 问题四:用100 cm长的绳子围一个矩形,当矩形的一边长x 分别为 30 cm,35 cm,40 cm,45 cm 时,它的邻边长y 分别为多少?y的值随x的变化而变化吗? 小结:以上这些问题都反映了不同事物的变化过程,其实现实生活中还有好多类似的问题,在这些变化过程中,有些量的值是按照某种规律变化的(如……),有些量的数值是始终不变的(如……)。 (二)归纳总结: 1、在一个变化过程中,我们称数值发生变化的量为________; 2、在一个变化过程中,我们称数值始终不变的量为________; (三)快速抢答: 练习1 指出下列问题中的变量和常量: (1)某市的自来水价为 4 元/t。现要抽取若干户居民调查水费支出情况,记某户月用水量为 x t,月应交水费为 y 元。 (2)某地手机通话费为 0.2 元/min ,李明在手机话费卡中存入30元,记此后他的手机通话时间为 t min ,话费卡中的余额为 w 元。 二、合作探究 (一)合作交流: 1、在研究的每个问题中,都出现了两个变量,它们之间是相互影响,相互制约的. 2、同一个问题中的变量之间有什么联系?(请同学们自己分析“问题一”中两个变量之间的关系,进而再分析上述所有实例中的两个变量之间是否有类似的关系.) 归纳:上面每个问题中的两个变量相互联系,当其中一个变量取定一个值时,另一个变量就有________确定的值与其对应。 (二)归纳概念: 一般地,在一个变化过程中,如果有两个变量x与y,并且对于x?的每一个确定的值,y?都有唯一确定的值与其对应,?那么我们就说x?是______,y是x的_______. 如果当x=a时y=b,那么b?叫做当自变量的值为a时的_________. 用关于自变量的数学式子表示函数与自变量之间的关系,是描述函数的常用方法.这种式子叫做函数的解析式. (三)巩固练习 练习2下列问题中哪些量是自变量?哪些量是自变量的函数?试写出函数的解析式。 (1)改变正方形的边长x,正方形的面积S 随之变化; (2)每分向一水池注水0.1 m3,注水量y(单位:m3)随注水时间x(单位:min)的变化而变化;