边楚女
浙江省新高考实施“7选3”模式后,技术成为其中的一门选考科目。“算法与程序设计”作为选考的考试内容,难度和广度有所提升,解析、枚举、排序、查找、递归等经典算法变成教学重点。同行们在教学研讨时常会提出一些问题:在学习这些经典算法时,如何让学生真正有效经历分析问题、确定算法、编程求解等计算机解决问题的基本过程,形成科学稳定的知识逻辑结构?是留白程序填空还是让学生自己独立编程?如何通过这些经典算法培养学生解决实际问题的能力?
2006年高中新课程改革之初,笔者学校就开设了“算法与程序设计”课程,当时也有教学这些经典算法,但由于那时要求不高,教学中教师的引导和指导较多,学生很多时候是靠填空程序来理解的。现在,在深化课程改革思想的推动下,课堂的教学模式和理念有了变革性的变化,以“学为中心”的课堂正逐渐成为新常态,所以,对这些经典算法的教授也应该进一步改进。
2007年,笔者曾在天津参加全国优质课展评活动,课题是“对分查找”。在那时这一课的设计和实施得到较广泛的认同,但现在回头来看,这节课的设计和教学有很多需要改进和提升的地方。前段时间,在给选考班上课时,我在原来设计的基础上对《对分查找》这一课作了改进,分成《对分查找算法实现》和《对分查找算法应用》两个课时,现以第一课时《对分查找算法实现》为例来解构我对这节课的设计和实施,以期抛砖引玉,与同行们一起努力建构更好的经典算法教学模式。我设定这一课时的主要教学目标为:理解对分查找的原理,通过分步解析各种查找情况,归纳对分查找的基本思想和方法,确定解题步骤,并最终独立完成程序编写。
课堂教学
1.设问引入对分查找算法
上课伊始,我问学生:“有一个数在1~100之间,请大家用最少的次数来猜出这个数。你会先猜几?”学生回答:“50。”“好,这个数在1到49之间,你会猜几?”“25。”“为什么你们最初会猜50,接下来猜25呢?”随后我再扔出一个问题:如果我告诉你这个数是15,按照刚才的逻辑,几次可以猜到这个数呢?与学生交流后,我说:“在刚才的沟通中,其实隐藏着一个非常经典的算法——对分查找。同学们应该能感觉到这种算法的存在,但它究竟是怎样的呢?”
教学阐析:原来设计课堂导入时,我会展示一件物品,让一个学生来猜这个物品的价格,其他学生根据这个学生猜出的价格提示“高了”或是“低了”。如果学生能在约定次数内猜对这个物品的价格,我就把这件物品“赠送”给他。为了节约教学成本,更快地切入正题,现在的我换了一种导入模式,争取在两三分钟内引入对分查找,同时让学生从互动讨论中预热对分查找的思想。
2.明确对分查找实施原理
在刚才沟通的基础上,我们先来明确对分查找实施原理:
(1)对分查找是效率很高的查找方法,但被查找的数据必须是有序的。
(2)首先将查找的数与有序数组内处于中间位置的数据比较,如果中间位置上的数与查找的数不同,根据有序性,就可确定应该在数组的前半部分还是后半部分继续查找。
(3)在新确定的范围内,继续按上述方法进行查找,直到获得最终结果。
教学阐析:这个环节,我直接告诉学生对分查找实施原理,让学生建构一个清晰的问题结构,以便正确导航接下来的学习。
3.分解查找过程中可能出现的第一种情况
明确了对分查找的实施原理,如何编出对分查找的程序呢?现以规模为10的升序数组d为例加以分析:用数组d(1 to 10)存放数据序列,用i表示查找范围的第一个数组元素下标,j表示最后一个数组元素下标,mid表示数组中间位置元素下标。
假如查找键key=48(如图1),学生经历的思考过程如下:
第一次查找:范围为d(1)~ d(10),i=1,j=10,mid=int((1+10)\ 2)=5,d(mid)=d(5)=22,key=48,d(mid) 第二次查找:新的数据查找范围为d(6)~d(10),mid=int((6+ 10)\2)=8,d(mid)=d(8)=45,key= 48,d(mid) 第三次查找:新的数据查找范围为d(9)~d(10),mid=int((9+ 10)\2)=9,d(mid)=48,key=48,d(mid)=key,找到啦!查找结束! 在以上的分析过程中,我引导学生思考两个问题:①d(mid) 总结:如果d(mid) 教学阐析:我与学生共同完成第一种情况的分析,并通过两个思考题引导学生聚焦于问题的解决。有了这一过程,学生在接下来的独立分析环节就能把握方向。 4.分解查找过程中可能出现的第二种情况
假设查找键key=17(如图2),让学生在Excel中画出相应的查找示意图,并思考:当d(mid)>key时,新查找的范围在哪里?i和j如何变化?学生经历的思考过程如下:
第一次查找:范围为d(1)~ d(10),i=1,j=10,mid=int((1+ 10)\2)=5,d(mid)=d(5)=22,key= 17,d(mid)>key,确定接下来要找的范围是数据序列的前半部分。
第二次查找:新的数据查找范围为d(1)~d(4),mid=int ((1+3)\2)=2,d(mid)=d(2)=15,key=17,d(mid) 第三次查找:新的数据查找范围为d(3)~d(4),mid=int((3+ 4)\2)=3,d(mid)=d(3)=17,key=17,d(mid)=key,找到啦!查找结束! 总结:如果d(mid)>key,新查找范围为上半部分,i值不变,j=mid-1。 教学阐析:学生模仿第一种情况,自主经历问题的分析过程,厘清第二种查找情况的原理,得出i、j的变化规律。有了第一种情况的“导”,学生对第二种情况的“学”就能更有效,这样既发挥了教师导的作用,又培养了学生自主学习的能力。 5.分解查找过程中可能出现的第三种情况 假设查找键key=20(如图3),让学生在Excel中继续画出相应的查找示意图,并思考:在什么情况下查找会结束?继续进行重复查找的条件是什么? 学生经历的思考过程如下: 第一次查找:范围为d(1)~ d(10),i=1,j=10,mid=int((1+ 10)\2)=5,d(mid)=d(5)=22,key= 20,d(mid)>key,确定接下来要找的范围是数据序列的前半部分。 第二次查找:新的数据查找范围为d(1)~d(4),mid=int((1+3)\2)=2,d(mid)=d(2)=15,key=20,d(mid) 第三次查找:新的数据查找范围为d(3)~d(4),mid=int((3+ 4)\2)=3,d(mid)=d(3)=17,key=20,d(mid) 第四次查找:新的数据查找范围只有d(4),mid=int((4+4)\2)=4,d(mid)=d(4)=18,key=20,d(mid)≠key,最后只剩一个数据时,还是找不到,说明数据不在这个序列里,查找结束。 总结:①找到了查找会结束。②在i<=j时重复查找,如果还是找不到,查找也会结束。 教学阐析:在教师的宏观把握下,学生通过对渐次递进的三种情况的分析,主动把握住了对分查找实施的具体过程。同时,教师要明确的是,除了要总结出i、j的变化规律,什么时候查找会结束也是这节课的重难点。因此,让学生思考查找结束的情况也应该在分析问题的过程中及时介入,这样在接下来编写循环结构的判断条件时,学生的思考就有了落脚点。 6.对各种情况进行归纳总结 通过以上三种情况的分析,我们可以归纳如下: (1)key与d(mid)的大小比较影响i、j取值的规律: i的取值规律:如果d(mid) j的取值规律:如果d(mid)>key,那么j=mid-1。 (2)继续进行重复查找的条件:i≤j。 教学阐析:虽然前面分步提到了这些信息,但是课堂中很有必要整合这些结论,让学生从宏观上形成一个完整的知识结构。当然,教师不要一下子呈现这一知识结构,要引导学生自己表达。 7.用流程图来描述对分查找算法 教学阐析:教师不要一下子全部展示这个流程图(如图4),而应逐渐展开,在关键点上留白让学生口头填空。 8.对分查找算法程序实现 接下来,为了让学生聚焦到学习重点,我事先设计好了程序界面窗体,并生成了100个升序数据,学生的中心任务就是全心全意完成对分查找程序(如下页图5)。经过编写、调试、思考、改进和教师旁白引导、个别指导,绝大部分学生在20分钟内都能编写出完整的对分查找程序。 教学阐析:通过前面的铺垫分析,学生形成了清晰的问题解决逻辑结构,再加上一段时间学习养成的良好编程基本功,学生最终独立编写出了程序。以前由于担心学生没法完成这个任务,所以采用留白填空的方法。实践证明,如果教师有较好的教学规划,有培养学生自主学习和独立思考的意识,学生肯定能一次一次地坚实成长。 9.提升、巩固和总结 完成的学生把升序序列改成降序序列后再改动对分查找程序,同时研究对分查找最多的查找次数,最后通过几个选择题加以巩固。如果有时间,教师可以适当提升对分查找算法的实际意义:设想一下在一个有一百万个人名的电话簿中找一个名字,对分查找可以让你不超过21次就能找到指定的名字。如果你将世界上所有的人按照姓名排序,那么你在35次以内就能找到任何人。对分查找的实际应用价值还有哪些呢?下节课待续! 教学阐析:为了让学生充分内化对分查找算法,第二课时《对分查找算法应用》通过对分查找在求解高次方程实根等多个具体问题中的运用进一步巩固对分查找知识。 课堂综述 这节课没有先声夺人的情境铺垫,没有气氛热烈的小组合作,没有滔滔不绝的教师讲解,更多的是教师严密理性的引导和学生被激活的思考和实践。为了给学生充分的思考和实践,每个环节都不容拖沓,每个点都需无缝对接,这就需要教师精心备课,去除冗余语言,精心准备各个资源,把时间挤出来给学生自主学习。例如,在原来的教学设计中,学生是在纸上画数据序列变化情况,现在我让学生在Excel中进行研究,并事先输好数组元素和数据初始序列;在学生编程环节,窗体和数据序列都已经给学生准备好,学生只需把精力投入到对分查找的主体程序上。这样做的目的是让学生充分聚焦到学习重点上,让时间有限的一节课变得更有效,实现教学目标的最大化达成。当然,这些都是课堂背后的故事;上课时,教师则不要为了赶时间而语焉不清,不要为了赶进程而压缩需要充分思考的时间。特别是在编程实践部分,教师更需要让学生静下心来,在一个松弛的环境中研究,而不要在旁边说话“影响”学生,如“时间不多了,大家快一点”“有些同学已经完成任务了,没完成的同学抓紧时间”等。 观点总结 教虽无定法,但在经典算法教学时,我建议教师们把握这样的指导思想:减少形式主义的情境堆砌和华丽铺垫,多些实实在在的学习指导;教师切忌讲太多,要想方设法让学生真正亲历解决问题的全过程。教师在算法形成过程中可以引导学生,但在编程环节最好让学生独立编程。如果学生基础整体较弱,可以留白给学生填空,但是前面的分析过程还是要让其参与进来,而不是直接告诉他们“是什么”,应与他们一起走过“这是怎么来的”学习过程;如果学生基础较好,可以减少教师引导的部分,给学生更多自主思考和编程的时间。另外,教师备课时一定要建构清晰的知识结构,再通过配套的实际应用课,来提升学生用经典算法解决实际问题的能力。更重要的是,在“算法与程序设计”的基础学习阶段,教师要夯实学生的编程规范和基本功,一开始就让其养成独立编程的习惯,这样学生才能形成后续学习的良性循环。 经典算法课怎么上?一言以蔽之:摒弃形式主义,让思考、学习和实践真实地在课堂中发生!