Re: [問題] 請問大家都怎麼教別人遞迴和迴圈的基本 …
※ 引述《leeyinf (貓貓)》之銘言:
: 我有認識的朋友大學是非資訊(財金)相關科系畢業,
: 最近對寫程式有興趣,
: 可是她一直卡在遞迴和迴圈,這個部分...
: 我教了可是她還是不太理解,
要學會遞迴很簡單的,
只要滿足兩個條件,她就可以很輕鬆的學會,
第一個條件就是不要教她迴圈,
第二個條件就是虐待她哈哈哈。
首先,叫她寫一個函數叫作 bool f(int max),可以印出 "10",
但是如果輸入的 max 小於 10,就什麼都不印,
如果有印東西的話,傳回 true,沒印東西的話,傳回 false。
這個函數很簡單,她應該可以毫無障礙的寫出來。
然後,叫她寫一個函數叫作 bool g(int max),可以印出 "9" 跟 "10",
但是如果輸入的 max 小於 9,就什麼都不印,
如果有印東西的話,傳回 true,沒印東西的話,傳回 false。
這個函數很簡單,她應該可以毫無障礙的寫出來。
然後,叫她寫一個函數叫作 bool h(int max),可以印出 "8", "9", "10",
但是如果輸入的 max 小於 8,就什麼都不印,
如果有印東西的話,傳回 true,沒印東西的話,傳回 false。
這個函數很簡單,她應該可以毫無障礙的寫出來。
然後,叫她寫一個函數叫作 bool i(int max),可以印出 "7" "8" "9" "10",
但是如果輸入的 max 小於 7,就什麼都不印,
如果有印東西的話,傳回 true,沒印東西的話,傳回 false。
這個函數很簡單,她應該可以毫無障礙的寫出來。
然後,叫她寫一個函數叫作 ......
就這樣,虐待她寫完十個函數。
如果這個時候她腦袋清楚,而且沒有惱羞成怒的話,
你會發現她可能已經開始複用她的程式碼,在 f() 裡面呼叫 g(),
g() 裡面呼叫 h(),
h() 裡面呼叫 i(),
i() 裡面呼叫 j()...
如果她沒有這麼做的話,你要提示她,讓她重複使用她的程式碼。
而且每寫好一個函數,都要進行編譯跟測試,
嘗試呼叫每一個函數,檢查一下行為是否正確。
等她寫完十個函數 f, g, h, i, j, k, l, m, n, o,印出 1 到 10 之後,
你問她能不能理解這些函數在做什麼,應該是可以,
因為每個函數都呼叫別人,這對於一般人來說不會有任合理解上的障礙。
然後你跟她說,使用者可能會希望印出來的東西是可以控制的,
不一定都是 10 9 8 7 ...,可能也希望會是 20 19 18 17 ...
請他把這十個函數,加上一個參數 a,函數原型變成 bool f(int a, int max)。
等她把十個函數都改完以後,
問她:「你會不會覺得這十個函數作的事情根本一模一樣?」(廢話)
「會阿 ^^"」
「o() 跟 m() 根本一模一樣對吧?
雖然 o() 呼叫的是 m(),
m() 呼叫的是 n(),
好像不一樣,
但是因為 m() 跟 n() 根本一模一樣,
所以其實 o() 跟 m() 還是一樣,對吧?」
「對耶~」
「那既然一樣,你把 o() 裡面呼叫的 m(),改成 o()。」
然後編譯,測試,發現結果完全正確。
「你有沒有發現其實 f() 到 o() 根本都是同一個函數,只是名字不同。
就像寫了十個函數叫作 f1(), f2(), f3(),但是只有名字不一樣,
那既然作的事情都一樣,那我們只需要寫一次就好啦。」
然後請她把 f() 到 m() 全部刪掉。
而剩下的那個 o(a, max) 就是可以從 a 印到 max 的遞迴函數。
「所以遞迴其實很簡單,
你不要想成自己呼叫自己,你把她想成每個函數都呼叫別的函數,
只是這每一個函數的內容都一模一樣,
那既然一樣,我們就只需要寫一次,這樣有懂嗎?」
「有 ^O^ 你好聰明喔,好帥喔,明天我要嫁給你啦~明天我要嫁給你拉~」
==
個人經驗是「自己呼叫自己」對很多人來說就像是一個魔障一樣,無論如何無法跨越,
但是每一個已經學會函數的人,對於「自己呼叫別人」都可以毫無障礙的理解,
所以我覺得教遞迴的最好方法就是完全不要提到「自己呼叫自己」,
而是跟他說每個人都是呼叫別人,只是每個函數的實作內容都一模一樣,
我發現這樣講很多人都可以很簡單的吸收。
呼叫函數就是呼叫函數,呼叫的是自己還是別人根本沒有差。
所以最好讓他們在不知道什麼是「遞迴」的狀態下就寫出遞迴,
然後才跟他們說這叫作遞迴。
所以另外一個教法是使用「間接遞迴」,
可以設計一個誘導教程,讓 f() 用到 g(),然後 g() 會用到 f(),
然後再請對方把 f() 裡面的 g() 用 g() 的時作取代掉取代,
這樣 g() 就會消失,只留下 f() 呼叫 f()。這個時候再跟他說這就是遞迴。
不過我一下想不到怎麼設計小巧的題目作到這件事 = =
而且我覺得不會迴圈的人特別容易善用遞迴,
因為對他來說能重複做事情的唯一方法就是遞迴,
但是很多人都已經會了迴圈還要學遞迴,就有點可惜。
機會難得,好好把握。
--
To iterate is human, to recurse, divine.
遞迴只應天上有, 凡人該當用迴圈. L. Peter Deutsch
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 118.160.113.219
推
06/23 00:34, , 1F
06/23 00:34, 1F
推
06/23 00:37, , 2F
06/23 00:37, 2F
推
06/23 00:40, , 3F
06/23 00:40, 3F
推
06/23 00:46, , 4F
06/23 00:46, 4F
→
06/23 00:48, , 5F
06/23 00:48, 5F
→
06/23 00:48, , 6F
06/23 00:48, 6F
推
06/23 00:49, , 7F
06/23 00:49, 7F
推
06/23 00:53, , 8F
06/23 00:53, 8F
→
06/23 00:56, , 9F
06/23 00:56, 9F
→
06/23 01:06, , 10F
06/23 01:06, 10F
推
06/23 01:35, , 11F
06/23 01:35, 11F
推
06/23 01:44, , 12F
06/23 01:44, 12F
→
06/23 01:51, , 13F
06/23 01:51, 13F
推
06/23 01:58, , 14F
06/23 01:58, 14F
推
06/23 02:11, , 15F
06/23 02:11, 15F
推
06/23 02:57, , 16F
06/23 02:57, 16F
推
06/23 07:13, , 17F
06/23 07:13, 17F
推
06/23 10:06, , 18F
06/23 10:06, 18F
推
06/23 13:20, , 19F
06/23 13:20, 19F
→
06/23 13:21, , 20F
06/23 13:21, 20F
推
06/23 13:26, , 21F
06/23 13:26, 21F
→
06/23 13:26, , 22F
06/23 13:26, 22F
→
06/23 13:28, , 23F
06/23 13:28, 23F
→
06/23 13:37, , 24F
06/23 13:37, 24F
推
06/23 14:56, , 25F
06/23 14:56, 25F
→
06/23 20:01, , 26F
06/23 20:01, 26F
→
06/23 20:11, , 27F
06/23 20:11, 27F
推
06/23 22:23, , 28F
06/23 22:23, 28F
推
06/28 13:20, , 29F
06/28 13:20, 29F
→
07/01 00:46, , 30F
07/01 00:46, 30F
→
07/01 19:25, , 31F
07/01 19:25, 31F
推
07/06 21:35, , 32F
07/06 21:35, 32F
討論串 (同標題文章)
完整討論串 (本文為第 2 之 5 篇):