浙江省金華師范附屬小學 潘洪波
遞歸是一種算法,無論是學習計算機語言,還是學習算法,遞歸一直伴隨其中;遞歸也是一種思維方式,許多復(fù)雜的問題用遞歸的方式來思考就很容易解決。采用遞歸算法編寫的程序直觀、易讀,理解遞歸概念,掌握遞歸本質(zhì),學會用遞歸編寫程序,對小學生以后的學習將有很大的幫助。筆者以六年級學生為教學對象,在編程社團中經(jīng)過幾年的實踐,總結(jié)出“準、明、歸、倒、煉”五步遞歸教學法。
準,即導入的案例要精準,能讓學生形成正確的第一感性認識。
小學生學習遞歸總是難以入門、難以掌握,為什么會這樣?常規(guī)課堂教學一般采用故事導入,如老和尚講故事——“從前有座山,山上有座廟,廟里有一個老和尚在給小和尚講‘從前有座山,山上有座廟,廟里有一個老和尚在給小和尚講……’”,或用“德羅斯特效應(yīng)”導入,比較經(jīng)典的就是一個人拿著一個相框,相框里他拿著相框……
用這類故事導入生動有趣,容易活躍課堂氣氛,但對理解遞歸的本質(zhì)是不利的。遞歸的本質(zhì)就是分而治之,通過“遞”將一個大型的、復(fù)雜的問題層層分解為若干與原問題性質(zhì)相同的、規(guī)模更小的子問題來處理,當規(guī)模小到一定程度時,可以直接得出它的解,然后利用“歸”,層層回歸、逐步向上求解就可以得到原問題的解。用函數(shù)實現(xiàn)時,因為解決大問題的方法和解決小問題的方法往往是同一種方法,所以就產(chǎn)生了直接或間接調(diào)用自身的情況。遞歸算法是一種“自己調(diào)用自己”“有去有回”的算法。
“老和尚講故事” “德羅斯特效應(yīng)”有的只是“自己調(diào)用自己”的重復(fù),但并沒有分而治之的思想(將大問題解決轉(zhuǎn)化成小的子問題),也沒出現(xiàn)遞歸結(jié)束條件,更沒有“遞”和“歸”以及“有去有回”的過程。用這類故事導入,容易讓學生形成一種錯誤的認識:遞歸就是重復(fù),遞歸就是循環(huán)。
第一印象、第一感知很重要,如果一開始就理解錯了,以后就更難學了。有沒有更好的例子呢?筆者選用《小學生C++趣味編程》中“交作業(yè)啦”為課堂導入的例子。
這個例子中有分而治之的思想:求第1 個學生交的作業(yè)數(shù),可以先求第2 個學生要交的作業(yè)數(shù);求第2個學生交的作業(yè)數(shù),可以先求第3 個學生要交的作業(yè)數(shù)……要解決的問題性質(zhì)不變但規(guī)模越來越小。每個學生都是收作業(yè),就是“自己調(diào)用自己”。前一個學生轉(zhuǎn)過去對后一個學生說“交作業(yè)啦”,這就是“遞”的過程?!暗? 個是格萊爾,她是一組中的最后一個學生”,這就是遞歸結(jié)束條件,可以直接得出它的解。把自己的作業(yè)連同收到的作業(yè)交給前一個同學,這就是“歸”的過程?!敖蛔鳂I(yè)啦”完整地演繹了遞歸算法的“自己調(diào)用自己” “有去有回”的過程,能讓學生形成正確的第一感性認識。
明,即讓學生明白遞歸的概念及遞歸程序的執(zhí)行過程。教學時可以先分析執(zhí)行過程再提出概念,這樣就能讓學生在動態(tài)的過程中理解靜態(tài)的概念。
遞歸程序在執(zhí)行時分兩步:第一步是“遞歸前進”;第二步是“遞歸返回”。要想讓學生明白這一過程,教師可以畫一畫遞歸執(zhí)行圖。(見圖1)
圖1 遞歸執(zhí)行圖
學生在繪制“遞”與“歸”的路徑中動態(tài)地理解遞歸概念。程序執(zhí)行zuoye(1)時,要調(diào)用zuoye(2);執(zhí)行zuoye(2)時,要調(diào)用zuoye(3)……執(zhí)行zuoye(6)時,要調(diào)用zuoye(7),這就是“遞歸前進”。zuoye(7)為1,求出zuoye(6)為2; zuoye(6)為2,求出zuoye(5)為3……最后求出zuoye(1)為7,這就是“遞歸返回”。
歸,即根據(jù)遞歸執(zhí)行圖,找到邊界條件及邊界值,歸納出遞歸表達式。在歸納遞歸表達式時,先寫出分步表達式,再歸納出綜合表達式,因為分步表達式會在題目中直接或間接地呈現(xiàn),容易寫出,而綜合表達式需要推理才能得出,難度大一些,在此要遵循先簡單后復(fù)雜的原則。
分步表達式:
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
綜合表達式:
這樣,根據(jù)遞歸表達式寫出程序就容易多了。
在此過程中,教師要讓學生明白,遞歸表達式是解決問題的通式,掌握歸納遞歸表達式的方法——可以先寫出分步表達式,找出其中的規(guī)律,再寫出綜合表達式。同時要讓學生明白,并不是所有的問題都能用遞歸的方法來解決,用遞歸解決問題時是有條件的:原問題可轉(zhuǎn)化為規(guī)模更小的子問題,子問題和原問題有相同的解決方法;問題可以繼續(xù)轉(zhuǎn)化,轉(zhuǎn)化后問題規(guī)模更??;在有限次轉(zhuǎn)化后,根據(jù)遞歸結(jié)束的條件(邊界條件)能得到最小子問題的值(邊界值)。
倒,即根據(jù)程序倒推出遞歸表達式,畫出遞歸執(zhí)行圖,并說一說程序的作用,進行鞏固練習,只有鞏固后才能應(yīng)用。這個過程可以借助于閱讀程序?qū)懡Y(jié)果方式進行由淺入深的訓練。
可以先讓學生說一說、寫一寫上面這個程序遞歸表達式,在說和寫遞歸表達式時,要先綜合表達式后分步表達式(因為此時綜合表達式、邊界條件和邊界值在程序中能找到,而分步表達式需要推理才能得出,所以寫出綜合表達式比分步表達式容易),然后畫一畫遞歸執(zhí)行圖,交流“遞”與“歸”的具體執(zhí)行路徑,最后思考程序的功能。
同時也可以引導學生針對遞歸的問題用遞推的方式來解,先找到最小問題的解,然后逐步求稍大問題的解,最后求出原問題的解,為遞歸與遞推的轉(zhuǎn)化做鋪墊。
需要注意的是,入門階段遞歸函數(shù)參數(shù)的個數(shù)要少,建議用一個,不用兩個或多個,主程序調(diào)用遞歸函數(shù)實參數(shù)值要小,建議在5 以內(nèi),這樣易于小學生分析、畫圖、理解,可以節(jié)約時間、提高學習效率。
煉,即提煉出編寫遞歸程序的方法,以實現(xiàn)學以致用。
這個過程以上機編程訓練為主,訓練時可分兩步走:第一步,根據(jù)已知邊界條件和邊界值、遞歸表達式直接寫出程序;第二步,根據(jù)問題描述,由學生自己找出邊界條件和邊界值,推導出遞歸表達式,然后編寫程序。
所選的題目題意要淺顯,要讓學生很容易就能找到邊界條件和邊界值,歸納出遞歸表達式。學生不應(yīng)花大量的時間在數(shù)學分析上、花大量的精力在數(shù)學公式的推導上,應(yīng)把時間和精力放在“遞歸”本身上。題目只是載體,學生通過這個載體來學習、鞏固、提高、應(yīng)用遞歸算法。