Aby wyjaśnić rekurencję , używam kombinacji różnych wyjaśnień, zwykle w celu:
- wyjaśnić pojęcie,
- wyjaśnij, dlaczego to ma znaczenie,
- wyjaśnij, jak to zdobyć.
Na początek Wolfram | Alpha definiuje to w prostszych terminach niż Wikipedia :
Wyrażenie takie, że każdy termin jest generowany przez powtórzenie określonej operacji matematycznej.
Matematyka
Jeśli twój uczeń (lub osoba, którą również wyjaśnisz, odtąd powiem studentowi) ma przynajmniej pewne podłoże matematyczne, najwyraźniej już spotkał się z rekurencją, studiując serie i ich pojęcie rekurencyjności oraz ich relację powtarzalności .
Bardzo dobrym sposobem na rozpoczęcie jest następnie zademonstrowanie za pomocą serii i powiedzenie, że po prostu chodzi o rekurencję:
- funkcja matematyczna ...
- ... który wywołuje się do obliczenia wartości odpowiadającej n-temu elementowi ...
- ... i który określa pewne granice.
Zazwyczaj dostajesz „huh huh, whatev”, co najwyżej, ponieważ nadal go nie używają, lub bardziej prawdopodobne jest to bardzo głębokie chrapanie.
Przykłady kodowania
Co do reszty, to faktycznie szczegółowa wersja tego, co przedstawiono w uzupełnieniu do mojej odpowiedzi na pytania, które wskazał w zakresie wskaźników (zły pun).
Na tym etapie moi uczniowie zwykle wiedzą, jak wydrukować coś na ekranie. Zakładając, że używamy C, wiedzą, jak wydrukować pojedynczy znak za pomocą write
lub printf
. Wiedzą także o pętlach sterowania.
Zwykle uciekam się do kilku powtarzających się i prostych problemów programistycznych, dopóki ich nie otrzymają:
- silnia operacja,
- drukarka alfabetyczna,
- drukarka z odwróconym alfabetem,
- exponentation operacja.
Factorial
Factorial to bardzo prosta koncepcja matematyczna do zrozumienia, a jej implementacja jest bardzo zbliżona do jej matematycznej reprezentacji. Jednak na początku mogą go nie otrzymać.
Alfabety
Wersja alfabetyczna jest interesująca, aby nauczyć ich myśleć o kolejności ich rekurencyjnych instrukcji. Podobnie jak w przypadku wskaźników, będą rzucać w ciebie losowo liniami. Chodzi o to, aby uświadomić im, że pętlę można odwrócić, modyfikując warunki LUB po prostu odwracając kolejność instrukcji w funkcji. Tutaj pomaga wydrukowanie alfabetu, ponieważ jest to dla nich coś wizualnego. Po prostu poproś, aby napisali funkcję, która wypisze jeden znak dla każdego wywołania i wywoła się rekurencyjnie, aby napisać następny (lub poprzedni).
Fani FP pomijają fakt, że drukowanie rzeczy do strumienia wyjściowego jest na razie efektem ubocznym ... Nie denerwujmy się na froncie FP. (Ale jeśli używasz języka z obsługą list, nie krępuj się łączyć z listą przy każdej iteracji i po prostu drukować końcowy wynik. Ale zwykle zaczynam je od C, co niestety nie jest najlepsze dla tego rodzaju problemów i koncepcji) .
Potęgowanie
Problem potęgowania jest nieco trudniejszy ( na tym etapie nauki). Oczywiście koncepcja jest dokładnie taka sama jak dla silni i nie ma dodatkowej złożoności ... oprócz tego, że masz wiele parametrów. I to zwykle wystarcza, aby zmylić ludzi i odrzucić ich na początku.
Jego prosta forma:
można wyrazić w następujący sposób:
Trudniej
Po pokazaniu tych prostych problemów ORAZ ponownym ich wdrożeniu w samouczkach możesz wykonać nieco trudniejsze (ale bardzo klasyczne) ćwiczenia:
- W Fibonacciego Liczby,
- Największy wspólny dzielnik ,
- Problem 8-królowych ,
- Gra Towers of Hanoi ,
- A jeśli masz środowisko graficzne (lub możesz udostępnić kody pośredniczące dla niego lub dla danych wyjściowych terminala lub mogą one już to zarządzać), na przykład:
- Aby uzyskać praktyczne przykłady, rozważ napisanie:
- algorytm przejścia drzewa,
- prosty parser wyrażeń matematycznych,
- gra trałowiec.
Uwaga: Ponownie niektóre z nich nie są wcale trudniejsze ... Po prostu podchodzą do problemu dokładnie pod tym samym lub nieco innym kątem. Ale praktyka czyni mistrza.
Pomocnicy
Referencja
Niektóre czytanie nigdy nie boli. Na początku tak będzie, a oni poczują się jeszcze bardziej zagubieni. To coś, co rośnie na tobie i które siedzi z tyłu głowy, dopóki pewnego dnia nie zdasz sobie sprawy, że w końcu to dostałeś. A potem myślisz o tych rzeczach, które czytasz. Na razie wystarczyłyby rekursja , informatyka i strony z relacjami na Wikipedii.
Poziom / głębokość
Zakładając, że uczniowie nie mają dużego doświadczenia w programowaniu, zapewnij kody pośredniczące. Po pierwszych próbach daj im funkcję drukowania, która może wyświetlać poziom rekurencji. Pomaga wydrukowanie wartości liczbowej poziomu.
Diagram stosu jako szuflady
Wcięcie wydruku (lub wyniku poziomu) również pomaga, ponieważ daje kolejną wizualną reprezentację tego, co robi Twój program, otwierając i zamykając konteksty stosu, takie jak szuflady lub foldery w eksploratorze systemu plików.
Akronimy rekurencyjne
Jeśli twój uczeń jest już trochę zaznajomiony z kulturą komputerową, może już korzystać z niektórych projektów / oprogramowania o nazwach wykorzystujących rekurencyjne akronimy . Od pewnego czasu jest to tradycja, szczególnie w projektach GNU. Niektóre przykłady obejmują:
Rekurencyjne:
- GNU - „GNU nie jest uniksem”
- Nagios - „Nagios nie będzie nalegał na Sainthood”
- PHP - „Preprocesor hipertekstu PHP” (i oryginalna „Osobista strona główna”)
- Wino - „Wine Is Not an Emulator”
- Zile - „Zile Is Lossy Emacs”
Wzajemnie rekurencyjne:
- HURD - „HIRD demonów zastępujących Uniksa” (gdzie HIRD to „HURD interfejsów reprezentujących głębokość”)
Niech spróbują wymyślić własne.
Podobnie istnieje wiele przypadków rekurencyjnego humoru, takich jak rekurencyjna korekta wyszukiwania Google . Aby uzyskać więcej informacji na temat rekurencji, przeczytaj tę odpowiedź .
Pułapki i dalsza nauka
Niektóre problemy, z którymi zwykle borykają się ludzie i na które musisz znać odpowiedzi.
Dlaczego, o Boże, dlaczego?
Dlaczego chcesz to zrobić? Dobrym, ale nieoczywistym powodem jest to, że często łatwiej jest wyrazić w ten sposób problem. Niezbyt dobrym, ale oczywistym powodem jest to, że często wymaga mniej pisania na klawiaturze (nie sprawiając, że czują się tak lojalni po prostu za pomocą rekurencji ...).
Niektóre problemy są zdecydowanie łatwiejsze do rozwiązania przy zastosowaniu podejścia rekurencyjnego. Zazwyczaj każdy problem, który można rozwiązać za pomocą paradygmatu Divide and Conquer , pasuje do wielorakiego algorytmu rekurencyjnego.
Co znowu N?
Dlaczego moja n
lub (niezależnie od nazwy zmiennej) za każdym razem jest inna? Początkujący zazwyczaj mają problem ze zrozumieniem, czym jest zmienna i parametr oraz jak rzeczy nazwane n
w twoim programie mogą mieć różne wartości. Więc teraz, jeśli ta wartość znajduje się w pętli sterowania lub rekurencji, jest jeszcze gorzej! Bądź miły i nie używaj wszędzie tych samych nazw zmiennych i wyraź, że parametry są tylko zmiennymi .
Warunki końcowe
Jak określić stan końcowy? To proste, po prostu niech mówią głośno. Na przykład dla silni zacznij od 5, następnie 4, a następnie ... aż do 0.
Diabeł tkwi w szczegółach
Nie rozmawiaj o wczesnych rzeczach, takich jak optymalizacja wezwania ogona . Wiem, wiem, TCO jest fajne, ale na początku ich to nie obchodzi. Daj im trochę czasu na owinięcie głowy procesem w sposób, który będzie dla nich odpowiedni. Zachęcamy do późniejszego rozbicia ich świata, ale dajcie im spokój.
Podobnie, nie mów prosto z pierwszego wykładu o stosie wywołań i zużyciu pamięci i ... cóż ... przepełnienie stosu . Często prowadzę prywatne zajęcia dla nauczycieli, którzy pokazują mi wykłady, na których mają 50 slajdów o wszystkim, co należy wiedzieć o rekurencji, kiedy na tym etapie ledwo potrafią poprawnie napisać pętlę. To dobry przykład tego, jak odniesienie pomoże później , ale teraz po prostu myli cię głęboko.
Ale proszę we właściwym czasie wyjaśnić, że istnieją powody, aby wybrać trasę iteracyjną lub rekurencyjną .
Wzajemna rekurencja
Widzieliśmy, że funkcje mogą być rekurencyjne, a nawet mogą mieć wiele punktów wywoławczych (8-królowych, Hanoi, Fibonacciego, a nawet algorytm eksploracji trałowca). Ale co z wzajemnie rekurencyjnymi połączeniami ? Zacznij od matematyki tutaj. f(x) = g(x) + h(x)
gdzie g(x) = f(x) + l(x)
a h
i l
po prostu zrobić rzeczy.
Rozpoczynanie od samych serii matematycznych ułatwia pisanie i implementację, ponieważ wyrażenia jasno definiują kontrakt. Na przykład sekwencje żeńskie i męskie Hofstadter :
Jednak jeśli chodzi o kod, to należy zauważyć, że realizacja wzajemnie rekurencyjne rozwiązania często prowadzi do powielania kodu, a raczej powinno być usprawnione w pojedynczą postać rekurencyjną (Patrz Peter Norvig „s Rozwiązywanie Każdy Sudoku .