小学编程社团中递归“五步”教学法
递归是一种算法,无论是学习计算机语言,还是学习算法,递归一直伴随其中;递归也是一种思维方式,许多复杂的问题用递归的方式来思考就很容易解决。采用递归算法编写的程序直观、易读,理解递归概念,掌握递归本质,学会用递归编写程序,对小学生以后的学习将有很大的帮助。笔者以六年级学生为教学对象,在编程社团中经过几年的实践,总结出“准、明、归、倒、炼”五步递归教学法。
准,即导入的案例要精准,能让学生形成正确的第一感性认识。
小学生学习递归总是难以入门、难以掌握,为什么会这样?常规课堂教学一般采用故事导入,如老和尚讲故事——“从前有座山,山上有座庙,庙里有一个老和尚在给小和尚讲‘从前有座山,山上有座庙,庙里有一个老和尚在给小和尚讲……”,或用“德罗斯特效应”导入,比较经典的就是一个人拿着一个相框,相框里他拿着相框……
用这类故事导入生动有趣,容易活跃课堂气氛,但对理解递归的本质是不利的。递归的本质就是分而治之,通过“递”将一个大型的、复杂的问题层层分解为若干与原问题性质相同的、规模更小的子问题来处理,当规模小到一定程度时,可以直接得出它的解,然后利用“归”,层层回归、逐步向上求解就可以得到原问题的解。用函数实现时,因为解决大问题的方法和解决小问题的方法往往是同一种方法,所以就产生了直接或间接调用自身的情况。递归算法是一种“自己调用自己”“有去有回”的算法。
“老和尚讲故事”“德罗斯特效应”有的只是“自己调用自己”的重复,但并没有分而治之的思想(将大问题解决转化成小的子问题),也没出现递归结束条件,更没有“递”和“归”以及“有去有回”的过程。用这类故事导入,容易让学生形成一种错误的认识:递归就是重复,递归就是循环。
第一印象、第一感知很重要,如果一开始就理解错了,以后就更难学了。有没有更好的例子呢?笔者选用《小学生C++趣味编程》中“交作业啦”为课堂导入的例子。
这个例子中有分而治之的思想:求第1个学生交的作业数,可以先求第2个学生要交的作业数;求第2个学生交的作业数,可以先求第3个学生要交的作业数……要解决的问题性质不变但规模越来越小。每个学生都是收作业,就是“自己调用自己”。前一个学生转过去对后一个学生说“交作业啦”,这就是“递”的过程。“第7个是格莱尔,她是一组中的最后一个学生”,这就是递归结束条件,可以直接得出它的解。把自己的作业连同收到的作业交给前一个同学,这就是“归”的过程。“交作业啦”完整地演绎了递归算法的“自己调用自己”“有去有回”的过程,能让学生形成正确的第一感性认识。
明,即让学生明白递归的概念及递归程序的执行过程。教学时可以先分析执行过程再提出概念,这样就能让学生在动态的过程中理解静态的概念。
递归程序在执行时分两步:第一步是“递归前进”;第二步是“递归返回”。要想让学生明白这一过程,教师可以画一画递归执行图。(见图1)
学生在绘制“递”与“归”的路径中动态地理解递归概念。程序执行zuoye(1)时,要调用zuoye(2);执行zuoye(2)时,要调用zuoye(3)……执行zuoye(6)时,要调用zuoye(7),这就是“递归前进”。zuoye(7)为1,求出zuoye(6)为2;zuoye(6)为2,求出zuoye(5)为3……最后求出zuoye(1)为7,这就是“递归返回”。
归,即根据递归执行图,找到边界条件及边界值,归纳出递归表达式。在归纳递归表达式时,先写出分步表达式,再归纳出综合表达式,因为分步表达式会在题目中直接或间接地呈现,容易写出,而综合表达式需要推理才能得出,难度大一些,在此要遵循先简单后复杂的原则。
分步表达式:
zuoye(1)=zuoye(2)+1
zuoye(2)=zuoye(3)+1
zuoye(3)=zuoye(4)+1
zuoye(4)=zuoye(5)+1
zuoye(5)=zuoye(6)+1
zuoye(6)=zuoye(7)+1
zuoye(7)=1
综合表达式:
这样,根据递归表达式写出程序就容易多了。
在此过程中,教师要让学生明白,递归表达式是解决问题的通式,掌握归纳递归表达式的方法——可以先写出分步表达式,找出其中的规律,再写出综合表达式。同时要让学生明白,并不是所有的问题都能用递归的方法来解决,用递归解决问题时是有条件的:原问题可转化为规模更小的子问题,子问题和原问题有相同的解决方法;问题可以继续转化,转化后问题规模更小;在有限次转化后,根据递归结束的条件(边界条件)能得到最小子问题的值(边界值)。
倒,即根据程序倒推出递归表达式,画出递归执行图,并说一说程序的作用,进行巩固练习,只有巩固后才能应用。这个过程可以借助于阅读程序写结果方式进行由浅入深的训练。
可以先让学生说一说、写一写上面这个程序递归表达式,在说和写递归表达式时