Anatomia definicji rekursywnej. Anatomia definicji rekursywnej. int silnia(intn){ if(n==0) return 1; else return n*silnia(n-1); }

Podobne dokumenty
Poprawność semantyczna

Wstęp do programowania

Indukcja. Materiały pomocnicze do wykładu. wykładowca: dr Magdalena Kacprzak

Podstawowe algorytmy i ich implementacje w C. Wykład 9

Poszukiwanie liniowe wśród liczb naturalnych

Wykład 2. Poprawność algorytmów

Algorytmy i Struktury Danych

Rekurencja/rekursja. Iluzja istnienia wielu kopii tego samego algorytmu (aktywacji) Tylko jedna aktywacja jest aktywna w danej chwili

TEORETYCZNE PODSTAWY INFORMATYKI

WYKŁAD 8. Funkcje i algorytmy rekurencyjne Proste przykłady. Programy: c3_1.c..., c3_6.c. Tomasz Zieliński

Zadanie 1 Przygotuj algorytm programu - sortowanie przez wstawianie.

Wstęp do programowania. Dziel i rządź. Piotr Chrząstowski-Wachtel

Teoretyczne podstawy informatyki

Podstawy Informatyki. Sprawność algorytmów

Komentarze w PHP (niewykonywane fragmenty tekstowe, będące informacją dla programisty)

Programowanie - wykład 4

Teoretyczne podstawy informatyki

Wykład 3. Metoda dziel i zwyciężaj

Wieczorowe Studia Licencjackie Wrocław, Wykład nr 6 (w oparciu o notatki K. Lorysia, z modyfikacjami) Sito Eratostenesa

Zaawansowane algorytmy i struktury danych

Podstawowe elementy programu. patrz: następne 2 slajdy. Podstawowe elementy programu. Komendy proste:

Opis zagadnieo 1-3. Iteracja, rekurencja i ich realizacja

Wykład 8. Rekurencja. Iterować jest rzeczą ludzką, wykonywać rekursywnie boską. L. Peter Deutsch

Strategia "dziel i zwyciężaj"

REKURENCJA W JĘZYKU HASKELL. Autor: Walczak Michał

Programowanie komputerowe. Zajęcia 3

Indukcja matematyczna, zasada minimum i maksimum. 17 lutego 2017

Algorytmy i Struktury Danych.

Informacje wstępne #include <nazwa> - derektywa procesora umożliwiająca włączenie do programu pliku o podanej nazwie. Typy danych: char, signed char

Błędy leksykalne są na ogół nietrudne do znalezienia.

Podstawy Programowania C++

Algorytm selekcji Hoare a. Łukasz Miemus

Wstęp do Informatyki zadania ze złożoności obliczeniowej z rozwiązaniami

wykład II uzupełnienie notatek: dr Jerzy Białkowski Programowanie C/C++ Język C - funkcje, tablice i wskaźniki wykład II dr Jarosław Mederski Spis

Algorytmy i złożoność obliczeniowa. Wojciech Horzelski

Rodzaje błędów w programach. Wykład9.UWAGIOGÓLNE,str.1

FUNKCJA REKURENCYJNA. function s(n:integer):integer; begin if (n>1) then s:=n*s(n-1); else s:=1; end;

Algorytm. a programowanie -

Programowanie w C++ Wykład 2. Katarzyna Grzelak. 5 marca K.Grzelak (Wykład 1) Programowanie w C++ 1 / 41

Wstęp do programowania

Programowanie Proceduralne

Algorytmy i Struktury Danych. (c) Marcin Sydow. Sortowanie Selection Sort Insertion Sort Merge Sort. Sortowanie 1. Listy dowiązaniowe.

Rekurencja (rekursja)

Wstęp do programowania

Podstawy programowania. Wykład Funkcje. Krzysztof Banaś Podstawy programowania 1

Definicja. Ciąg wejściowy: Funkcja uporządkowująca: Sortowanie polega na: a 1, a 2,, a n-1, a n. f(a 1 ) f(a 2 ) f(a n )

Programowanie w C++ Wykład 2. Katarzyna Grzelak. 4 marca K.Grzelak (Wykład 1) Programowanie w C++ 1 / 44

Logika i teoria mnogości Wykład 14

Programowanie proceduralne INP001210WL rok akademicki 2017/18 semestr letni. Wykład 3. Karol Tarnowski A-1 p.

Sortowanie przez scalanie

Algorytmy i struktury danych. Co dziś? Tytułem przypomnienia metoda dziel i zwyciężaj. Wykład VIII Elementarne techniki algorytmiczne

Wskaźniki w C. Anna Gogolińska

ALGORYTMY I STRUKTURY DANYCH

Matematyka dyskretna. Andrzej Łachwa, UJ, /15

Funkcje. Funkcje. liczba rzeczywista r punkt, w którym wartość wielomianu nas interesuje. Szukane: liczba rzeczywista

Język JAVA podstawy. Wykład 3, część 3. Jacek Rumiński. Politechnika Gdańska, Inżynieria Biomedyczna

Tablice cz. I Tablice jednowymiarowe, proste operacje na tablicach

Wykład 4: Iteracja, indukcja i rekurencja

Matematyczne Podstawy Informatyki

Rekurencje. Jeśli algorytm zawiera wywołanie samego siebie, jego czas działania moŝe być określony rekurencją. Przykład: sortowanie przez scalanie:

Podstawy Informatyki. Algorytmy i ich poprawność

Zaawansowane algorytmy i struktury danych

Kontrola przebiegu programu

Matematyka dyskretna. Andrzej Łachwa, UJ, a/15

Indukcja matematyczna

Podstawy Programowania 1 Sortowanie tablic jednowymiarowych. Plan. Sortowanie. Sortowanie Rodzaje sortowania. Notatki. Notatki. Notatki.

Podstawy programowania 2. Temat: Drzewa binarne. Przygotował: mgr inż. Tomasz Michno

Algorytmy i Struktury Danych, 2. ćwiczenia

Testy jednostkowe Wybrane problemy testowania metod rekurencyjnych

TEORETYCZNE PODSTAWY INFORMATYKI

4. Funkcje. Przykłady

Metody Metody, parametry, zwracanie wartości

Jarosław Wróblewski Matematyka Elementarna, zima 2014/15

Ciągi komplementarne. Autor: Krzysztof Zamarski. Opiekun pracy: dr Jacek Dymel

main( ) main( void ) main( int argc, char argv[ ] ) int MAX ( int liczba_1, liczba_2, liczba_3 ) źle!

PDF stworzony przez wersję demonstracyjną pdffactory Pro Program 15

Podstawy programowania w języku C++

Algorytmy i złożoności. Wykład 3. Listy jednokierunkowe

Podstawy programowania 2. Temat: Funkcje i procedury rekurencyjne. Przygotował: mgr inż. Tomasz Michno

Podstawy informatyki. Informatyka stosowana - studia niestacjonarne. Grzegorz Smyk. Wydział Inżynierii Metali i Informatyki Przemysłowej

Algorytmy i Struktury Danych, 2. ćwiczenia

Podstawy programowania. Wykład Pętle. Tablice. Krzysztof Banaś Podstawy programowania 1

Temat: Dynamiczne przydzielanie i zwalnianie pamięci. Struktura listy operacje wstawiania, wyszukiwania oraz usuwania danych.

5. Rekurencja. Przykłady

Wykład 6. Metoda eliminacji Gaussa: Eliminacja z wyborem częściowym Eliminacja z wyborem pełnym

Część 4 życie programu

Rekurencja, schemat rekursji i funkcje pierwotnie rekurencyjne

Podstawy algorytmiki i programowania - wykład 3 Funkcje rekurencyjne Wyszukiwanie liniowe i binarne w tablicy

Podstawy algorytmiki i programowania - wykład 2 Tablice dwuwymiarowe cd Funkcje rekurencyjne

Analiza algorytmów zadania podstawowe

1 Funkcje uniwersalne

Matematyka Dyskretna 2/2008 rozwiązania. x 2 = 5x 6 (1) s 1 = Aα 1 + Bβ 1. A + B = c 2 A + 3 B = d

Zaawansowane algorytmy. Wojciech Horzelski

Język C, tablice i funkcje (laboratorium, EE1-DI)

Lab 9 Podstawy Programowania

WYKŁAD 9. Algorytmy sortowania elementów zbioru (tablic) Programy: c4_1.c... c4_3.c. Tomasz Zieliński

Matematyka dyskretna. Andrzej Łachwa, UJ, /14

Algorytmika i programowanie. Wykład 2 inż. Barbara Fryc Wyższa Szkoła Informatyki i Zarządzania w Rzeszowie

Technologie Informatyczne Wykład VII

Algorytmy i struktury danych. Wykład 6 Tablice rozproszone cz. 2

Transkrypt:

Anatomia definicji rekursywnej int silnia(intn){ if(n==0) return 1; else return n*silnia(n-1); PRZYPADEK BAZOWY PRZYPADEK REKURSYWNY Definicja rekursywna musi zawierać przypadek bazowy, czyli kod bez wywołania rekursywnego, wykonywany dla bardzo małych argumentów. Kod dla przypadków rekursywnych(może ich być więcej niż jeden), wykonywany dla pozostałych argumentów, składa się z wywołań rekursywnych dla mniejszych argumentów, oraz słowa wiążącego, zawierającego przejście od wyniku funkcji dla mniejszych argumentów do wyniku dla większych argumentów. Anatomia definicji rekursywnej Wykład 7. REKURSJA, str. Przykład: (ciąg Fibonacciego) F(0) def =0 F(1) def =1 F(n+) def =F(n+1)+F(n) 0 1 1 3 5 8 13 1 34 Rozrastanie się drzewa: Każdagałąźwjednymroku wypuszcza gałązkę potomną,awnastępnymodpoczywa. Rok6 8 Rok5 5 Rok4 3 Rok3 Rok 1

Anatomia definicji rekursywnej Przykład: (ciąg Fibonacciego) F(0) def =0 F(1) def =1 F(n+) def =F(n+1)+F(n) int Fib(intn) { if(n<=1) returnn; else return Fib(n-1)+Fib(n-); Powyższa definicja nie mówi wprost, czemu jest równy kolejny wyraz ciągu Fibonacciego; tylko jak przejść od wyrazów mniejszych do większych. Za resztę odpowiada mechanizm rekursji. Anatomia definicji rekursywnej Wykład 7. REKURSJA, str. 4 Przykład: (maksimum system pucharowy) double max(doublea[],intn,intk) { /* wyszukuje największą liczbę w ciągu a[n]...a[k-1]*/ int p; double m1,m; if(k-n==1) returna[n]; else { p=(n+k)/; m1=max(a,n,p); m=max(a,p,k); if(m1>m) returnm1; else return m; Powyższa definicja nie mówi wprost, jak znaleźć maksimum; tylko jak z maksimów ciągów krótszych zrobić maksimum ciągu dłuższego. Za resztę odpowiada mechanizm rekursji.

Anatomia definicji rekursywnej Przykład: (maksimum system pucharowy) 0 1 3 4 5 6 a: 17.0-1.5 33.3 0.01-15.8 3.15 1.34 0+ 0+4 0+9 4+9 +4 4+6 7.68 6+9 8 5.99 7+9 17.0-1.5 33.3 0.01-15.8 3.15 1.34.68 5.99 {{ {{{{{{ 17.0 33.3 3.15 5.99 {{ 5.99 {{ {{ 33.3 {{ 3.15 33.3 9 Zasady indukcji matematycznej Wykład 7. REKURSJA, str. 6 Zupełna: W(0) ( k<n W(k)) W(n) n W(n) Klasyczna: P(0) P(n) P(n+1) n P(n) TWIERDZENIE: Powyższe dwie zasady indukcji są równoważne. Dowód wynikania Z K: Załóżmy, że zachodzi P(0) oraz P(n) P(n+1) Wtedyzachodzirównież( k<n+1 P(k)) P(n+1),botaimplikacjajest słabszaodp(n) P(n+1).WobectegozregułyZmamy n P(n).

Zasady indukcji matematycznej Zupełna: W(0) ( k<n W(k)) W(n) n W(n) Klasyczna: P(0) P(n) P(n+1) n P(n) TWIERDZENIE: Powyższe dwie zasady indukcji są równoważne. Dowód wynikania Z K: Załóżmy,żezachodziW(0)oraz ( k<n W(k)) W(n) ( ). def Oznaczmy: P(n) k<n+1 W(k).WtedyP(0) W(0)oraz P(n) P(n)& k<n+1 W(k) ( ) P(n)&W(n+1) P(n+1) ZregułyKmamy n k<n+1 W(k),cojestrównoważne n W(n). Indukcja w logice filozoficznej Wykład 7. REKURSJA, str. 8 Wnioskowanie dedukcyjne: CODZIENNIE WSCHODZI SŁOŃCE 7 XII 008 wzeszło Słońce 6 XII 009 wzeszło Słońce 7 XII 009 wzeszło Słońce Wnioskowanie indukcyjne: CODZIENNIE WSCHODZI SŁOŃCE 7 XII 008 wzeszło Słońce 7 XII 009 wzeszło Słońce 6 XII 009 wzeszło Słońce

Indukcja w logice filozoficznej Rozumowanie indukcyjne: wyciąganie wniosków ogólnych ze szczególnych przypadków; np. wyprowadzanie praw natury z pojedynczych eksperymentów. Żeby indukcja była poprawną metodą wnioskowania, potrzebne są dodatkowe założenia. Klasyczna indukcja matematyczna oraz indukcja zupełna są poprawnymi metodami wnioskowania o własnościach liczb naturalnych; już dla liczb całkowitych zawodzą. Przy zastosowaniach informatycznych miara wielkości problemu musi być naturalna;np.wprzykładziemaxbyłaniąwielkośćk n. Badanie własności funkcji rekursywnej Wykład 7. REKURSJA, str. 10 double max(doublea[],intn,intk) { int p; double m1,m; if(k-n==1) returna[n]; else { p=(n+k)/; m1=max(a,n,p); m=max(a,p,k); if(m1>m) returnm1; else return m; TWIERDZENIE: Jeślin+1 k,to max(a,n,k) jest największą liczbą spośród a[n]...a[k-1]. Dowóddlaprzypadkuk n=1: Wtedyk=n+1,więcchodziociąga[n]...a[n],zawierającytylko jeden element a[n]; więc to ten element jest największy. I ten właśnie element funkcja oddaje.

Badanie własności funkcji rekursywnej double max(doublea[],intn,intk) { int p; double m1,m; if(k-n==1) returna[n]; else { p=(n+k)/; m1=max(a,n,p); m=max(a,p,k); if(m1>m) returnm1; else return m; TWIERDZENIE: Jeślin+1 k,to max(a,n,k) jest największą liczbą spośród a[n]...a[k-1]. Dowóddlaprzypadkuk n>1: Wtedyk n+,więcn<p<k. m 1 jestnajwiększaspośróda[n]...a[p-1]a m jestnajwiększaspośróda[p]...a[k-1], więc większa z nich jest największa w całym a[n]...a[k-1]. I tą właśnie liczbę funkcja oddaje. Schemat dowodu Udowodniliśmy, że Wykład 7. REKURSJA, str. 1 wprzypadkubazowymk m=1wywołaniefunkcjimax(a,m,k) działa poprawnie, wprzypadkurekursywnymk m>1wywołaniefunkcjimax(a,m,k) poprawnie konstruuje wynik z wyników wywołań max(a,m,k ), dla którychk m <k m. Stąd wyciągnęliśmy wniosek, że wywołanie max(a,m,k) działa poprawnie dladowolnegok m 1. W przypadku rekursywnym: założyliśmy, że poprawnie działają wewnętrzne wywołania max(a,m,k )dlak m <k m; z tego wywnioskowaliśmy, że poprawnie działa wywołanie max(a,m,k).

Zamiana iteracji for na rekursję Iteracja for daje się w zasadzie zastąpić wywołaniem funkcji rekursywnej zdefiniowanej bez użycia for-ów i while-ów: for(i=a; i<b; i=i+1) komenda; void ff(inti) { if(i<b) { komenda; ff(i+1); ff(a); Iteracja idzie naprzód, rekursja idzie w głąb. Efektjestwzasadzietensam. Zamiana iteracji for na rekursję Wykład 7. REKURSJA, str. 14 Przykład: (wypełnianie tablicy liczbami) for(i=0; i<100; i=i+1) tab[i]=i; void ff(inti) { if(i<100) { tab[i]=i; ff(i+1); ff(0); Dla dowolnej liczby naturalnej i, wywołanie ff(i) powoduje wypełnienie liczbami tablicy tab od pozycji i do pozycji 99 włącznie. Wywołanie ff(0) powoduje wypełnienie liczbami tablicy tab od pozycji 0 do pozycji 99 włącznie.

Zamiana pętli while na rekursję Pętla while daje się w zasadzie zastąpić wywołaniem funkcji rekursywnej zdefiniowanej bez użycia for-ów i while-ów: while(warunek) komenda; void ww() { if(warunek) { komenda;ww(); ww(); Pętla idzie naprzód, rekursja idzie w głąb. Efektjestwzasadzietensam. Zamiana pętli while na rekursję Wykład 7. REKURSJA, str. 16 Przykład: (szukanie liczby pierwszej większej od danej n) int k,i; int k,i; k=n+1; i=; while(i<k) if(k%i==0) { k=k+1; i=; else i=i+1; void ww() { if(i<k) { if(k%i==0) { k=k+1; i=; else i=i+1; ww(); k=n+1; i=; ww();

Zamiana pętli while na rekursję Przykład: (szukanie liczby pierwszej większej od danej n) int k,i; k=n+1; i=; while(i<k) if(k%i==0) { k=k+1; i=; else i=i+1; int ww(intk,inti) { if(i==k) returnk; else if(k%i==0) return ww(k+1, ); else return ww(k, i+1); ww(n+1,); Dladowolnejparyliczbkii,jeślikniedzielisięprzezżadnąliczbęmiędzy a i 1 włącznie, to ww(k,i) jest najmniejszą liczbą pierwszą niemniejszą niżk. ww(n + 1,) jest najmniejszą liczbą pierwszą większą od n. Zamiana pętli while na rekursję Wykład 7. REKURSJA, str. 18 Efekt jest w zasadzie ten sam. Wyjątek od zasady: Każde wywołanie rekursywne zajmuje kawałek pamięci, więc bardzo głęboka rekursja kończy się błędem wyczerpania pamięci. Przykład: while(1==1) a=a+1; void qq() { if(1==1) { a=a+1;qq(); qq(); Pętla while: nieskończone działanie. Funkcja qq: Segmentation fault Naruszenie ochrony pamięci

Zamiana pętli while na rekursję każdy rodzaj pętli można łatwo zastąpić rekursją; przy takim zastępowaniu, jakie zademonstrowano na poprzednich slajdach, otrzymuje się tylko t.zw. rekursję ogonową(tail-recursion): w ciele funkcji nic się już po wywołaniu rekursywnym nie dzieje; siła rekursji jako metody programowania bierze się z możliwości wykonywania działań po wywołaniu rekursywnym; a więc nie z rekursji ogonowej; wiele problemów programistycznych prowadzi w sposób naturalny do rozwiązania rekursywnego; przy pewnych problemach pętla a przy innych rekursja jest właściwym narzędziem; wybór należy do programisty; zastąpienie rekursji pętlą jest zwykle trudne wymaga skomplikowanego zarządzania pamięcią komputera. Wykład 7. REKURSJA, str. 0 Sortowanie rekursywne scalanie(merge-sort) double a[n]; void mergesort(intp,intq) { // porządkuje elementy tablicy //oda[p]doa[q-1]włącznie intr; if(p+1<q) { r=(p+q)/; mergesort(p,r); mergesort(r,q); merge(p,r,q); Funkcja merge scala niemalejące ciągi a[p]...a[r-1] i a[r]...a[q-1] wniemalejącyciąga[p]...a[q-1].

Sortowanie rekursywne scalanie(merge-sort) a: 0 17.0 1-1.5 33.3 3 0.01 4-15.8 5 3.15 6 1.34 7.68 8 5.99 9-1.5 17.0 0.01 33.3-15.8 3.15 1.34.68 5.99-1.5 0.01 17.0 33.3-15.8 3.15 1.34.68 5.99-1.5 0.01 17.0 33.3-15.8 1.34.68 5.99 3.15-15.8-1.5 0.01 1.34.68 5.99 17.0 3.15 33.3 Wykład 7. REKURSJA, str. Sortowanie rekursywne scalanie(merge-sort) double a[n]; void merge(intp,intr,intq) { // scala niemalejące ciągi a[p]...a[r-1] i //a[r]...a[q-1]wniemalejącyciąga[p]...a[q-1] inti,j,k; doublepom[n]; i=p; j=r; k=p; while(i<r&&j<q) { if(a[i] <= a[j]) { pom[k]=a[i]; i=i+1; k=k+1; else { pom[k]=a[j]; j=j+1; k=k+1; while(i<r) { pom[k]=a[i]; i=i+1; k=k+1; while(j<q) { pom[k]=a[j]; j=j+1; k=k+1; for(k=p; k<q; k=k+1) a[k]=pom[k];

Sortowanie przez scalanie(merge-sort) symulacja void mergesort(intp,intq) { intr; if(p+1<q) { r=(p+q)/; mergesort(p,r); mergesort(r,q); merge(p,r,q); Symulacja działania funkcji: mergesort(0,9); = = mergesort(0,4); mergesort(4,9); merge(0,4,9); = mergesort(0,); mergesort(,4); merge(0,,4); = mergesort(4,6); mergesort(6,9); merge(4,6,9); merge(0,4,9); = mergesort(0,1); mergesort(1,); merge(0,1,); = mergesort(,3); mergesort(3,4); merge(,3,4); merge(0,,4); = mergesort(4,5); mergesort(5,6); merge(4,5,6); = mergesort(6,7); mergesort(7,9); merge(6,7,9); merge(4,6,9); merge(0,4,9); = merge(0,1,); merge(,3,4); merge(0,,4); merge(4,5,6); = mergesort(7,9); merge(6,7,9); merge(4,6,9); merge(0,4,9); = Wykład 7. REKURSJA, str. 4 Sortowanie rekursywne scalanie(merge-sort) Oszacowanie czasu działania funkcji mergesort: Na scalenie dwóch ciągów długości n funkcja merge potrzebuje: gdziec 1 jestpewnąstałą. n porównań 4n przepisań razem c 1 n Załóżmy,żenjestpotęgą;iżedladowolnegok,T(k)jestczasem,jakiego mergesort potrzebuje na uporządkowanie ciągu długości k. T(n)= { c0 dlan=1 T( n )+c 1 n dlan>1 co się sprowadza do T(n) = c 1 n log n+c 0 n Dowód:indukcja(dlan potęgi).

Sortowanie rekursywne scalanie(merge-sort) Oszacowanie czasu działania funkcji mergesort: czas sortowania czas sortowania n bąbelkowegon przezscalanienlog n szybciejrazy czyli około: czyli około: 64 4096 384 11 104 1 000 000 10 000 100 10 6 10 1 10 7 50000 10 9 10 18 3 10 10 3 10 7 Wykład 7. REKURSJA, str. 6 Sortowanie rekursywne quick-sort-light double a[n]; void quicksort(intp,intq) { // porządkuje elementy tablicy //oda[p]doa[q-1]włącznie intk,l; doubler; if(p+1<q) { r=a[(p+q)/]; // rozdzielić ciąg a[p]...a[q-1] na trzy ciągi: // ciąga[p]...a[k-1]liczb<r // ciąga[k]...a[l-1]liczb=r // ciąga[l]...a[q-1]liczb>r quicksort(p,k); quicksort(l,q);