Algorytmy i Struktury Danych.
Transkrypt
Algorytmy i Struktury Danych.
Algorytmy i Struktury Danych. Rekurencja dr hab. Bożena Woźna-Szcześniak [email protected] Jan Długosz University, Poland Wykład 3 Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 3 1 / 61 Rekurencja I Rekurencja polega na rozwiazywaniu ˛ problemu w oparciu o rozwiazania ˛ tego samego problemu dla danych o mniejszych rozmiarach. W informatyce rekurencja jest technika˛ programistyczna, ˛ polegajac ˛ a˛ na wywoływaniu funkcji wewnatrz ˛ niej samej. Rekurencja jest jedna˛ z najbardziej interesujacych ˛ technik programistycznych i to w dodatku technika˛ zaskakujaco ˛ efektywna. ˛ Rekurencyjny opis obliczeń jest na ogół bardziej zwarty niż opis tych samych obliczeń bez użycia rekurencji. Taki opis jest stosowany np. przy opisie fraktali. Niektóre rozwiazania ˛ rekurencyjne moga˛ być nieefektywne. W takich przypadkach można je zastapić ˛ rozwiazaniami ˛ wykorzystujacymi ˛ zwyczajna˛ petle lub stos. Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 3 2 / 61 Rekurencja II Funkcja rekurencyjna cyklicznie wywołuje sama˛ siebie, za każdym razem przekazujac ˛ w wywołaniu inne argumenty. Przekazanie argumentu o pewnej wartości powoduje, że funkcja kończy działanie bez kolejnego wywołania samej siebie. Sytuacja ta jest nazywana przypadkiem bazowym. Gdy najbardziej ”wewnetrzne” ˛ wywołanie funkcji zostaje zakończone, rozpoczyna sie˛ proces zakańczania kolejnych wywołań, który w końcu doprowadza do zakonczenia poczatkowego wywołania. Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 3 3 / 61 Indukcja matematyczna Programowanie rekurencyjne jest bezpośrednio zwiazana ˛ z indukcja˛ matematyczna˛ - technika dowodzenia własności funkcji dyskretnych. Udowodnienie, że pewne twierdzenie odwołujace ˛ sie˛ do liczby całkowitej N jest prawdziwe dla nieskończenie wielu wartości N przy pomocy indukcji matematycznej składa sie˛ z dwóch etapów: Przypadek bazowy - udowadniamy, że twierdzenie jest prawdziwa dla jakiejś określonej wartości (zwykle 0 lub 1). Krok indukcyjny - główna cz˛eścia˛ dowodu. Zazwyczaj zakładamy, że twierdzenie jest prawdziwe dla wszystkich liczb całkowitych dodatnich mniejszych niż N, a nastepnie ˛ wykorzystujac ˛ ten fakt, udowodniamy, że jest prawdziwe dla N. Taki dowód jest wystarczajacy, ˛ aby wykazać, że twierdzenie jest prawdziwe dla wszystkich N. Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 3 4 / 61 Rozważane problemy rekurencyjne Funkcja silnia - Hello word dla rekurencji :) Algorytm Euklidesa Liczba trójkatna ˛ Potegi ˛ liczby naturalnej a Ciag ˛ Fibonacciego Wieże Hanoi Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 3 5 / 61 Funkcja silnia n! = 1 · 2 · . . . · n Algorytm iteracyjny: long long factorial(int n) { if (n==0) return 1; int i = 1; long long s = 1; while (i <= n) s *= i++; return s; } Require: Liczba n 1: i = 1; 2: silnia = 1; 3: while i <= n do 4: silnia = silnia * i; 5: i= i+1; 6: end while 7: return silnia; Złożoność czasowa: Θ(n). Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 3 6 / 61 Funkcja silnia - wersja rekurencyjna silnia(n) = 1 n ∗ silnia(n − 1) dla n = 0 Przypadek bazowy dla n > 0 Krok redukcji Ślad obliczeń: Kod C++: long long silnia(int n) { if (n==0) return 1; return n*silnia(n-1); } Bożena Woźna-Szcześniak (AJD) silnia(4) silnia(3) silnia(2) silnia(1) silnia(0) return 1 return 1*1 = 1 return 2*1 = 2 return 3*2 = 6 return 4*6 = 24 Algorytmy i Struktury Danych. Wykład 3 7 / 61 Czasowa złożoność obliczeniowa T (n) - czas potrzebny do wykonania funkcji silnia (n) dla dowolnego wejścia o rozmiarze n. Przypadek bazowy: T (0) = 1 (jednostkowy czas pracy, gdy algorytm działa na wejściu wielkości 1); Krok indukcyjny: Dla wejścia o rozmiarze n, algorytm wykonuje prace˛ jednostkowa˛ realizujac ˛ operacje porównania, mnożenia (tj. n ∗ silnia(n − 1)) oraz zwrotu wartości, a nastepnie ˛ wywołuje sam siebie dla wejścia o rozmiarze n − 1. Zatem otrzymujemy nastepuj ˛ ace ˛ równanie: T (n) = T (n − 1) + 1 dla n > 0. Jeśli rozwiniemy rekurencje˛ otrzymujemy: T (0) = 1, T (1) = T (0) + 1 = 1 + 1 = 2 T (2) = T (1) + 1 = 2 + 1 = 3, T (3) = T (2) + 1 = 3 + 1 = 4 T (4) = T (3) + 1 = 4 + 1 = 5, . . ., T (n) = n + 1 Zatem T (n) = Θ(n). Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 3 8 / 61 Najwiekszy ˛ Wspólny Dzielnik - Algorytm Euklidesa Wejście: dwie liczby naturalne a, b. Wyjście: najwiekszy ˛ wspólny dzielnik liczb a i b. Rozwiazanie ˛ rekurencyjne: NWD(a, b) = a NWD(b, a mod b) Bożena Woźna-Szcześniak (AJD) dla b = 0 dla b > 0 Algorytmy i Struktury Danych. Euklides z Aleksandrii ok. 365-300 p.n.e. Wykład 3 9 / 61 Najwiekszy ˛ Wspólny Dzielnik - kod C++ //wersja rekurencyjna long long NWD(int a, int b) { if (b==0) return a; else return NWD(b,a%b); } //wersja iteracyjna long long NWD2(int a, int b) { while (b != 0) { int temp = b; b = a % b; a = temp; } return a; } Bożena Woźna-Szcześniak (AJD) Ślad obliczeń nwd(1440, 408) nwd(408, 216) nwd(216, 192) nwd(192, 24) nwd(24, 0) return 24 return 24 return 24 return 24 return 24 Algorytmy i Struktury Danych. Wykład 3 10 / 61 Złożoność czasowa NWD Twerdzenie: Gabriel Lamé, 1844 Dla n ≥ 1, niech u i v bed ˛ a˛ liczbami całkowitymi takimi, że u > v > 0 oraz algorytm euklidesa zastosowany do u i v wymaga dokładnie n dzieleń oraz u jest najmniejsza˛ możliwa˛ wartościa˛ spełniajacych ˛ te warunki. Wówczas u = F (n + 2) oraz v = F (n + 1), gdzie F (k ) jest liczba˛ Fibonacciego a . Ponadto, liczba kroków algorytmu Euklidesa nie przekracza wartości 5 razy ilość cyfr w mniejszej liczbie. a (D. Knuth. The Art of Computer Programming, Tom. 2, Addison-Wesley, 1998., str. 343) Ograniczenie 5 może być dalej zmniejszone do ln(10)/lnφ , gdzie √ 1+ 5 (φ = 2 = 1.618033988749894848204586834365638117720 . . .) jest złotym podziałem. Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 3 11 / 61 Złożoność czasowa NWD Przykład: Niech a = 3 a b = 2. Algorytm NWD wykonał 2 obroty, aby obliczyć NWD z a i b: NWD(3, 2) = NWD(2, 1) = NWD(1, 0) = 1 Ograniczenie zgodne z Tw. Gabriel Lamé: 5 ∗ 1 = 5 Ulepszone ograniczenie: 1 · ln(10)/ln(1.62) = 4, 77 Przykład: Niech a = 8 a b = 5. Algorytm NWD wykonał 4 obroty, aby obliczyć NWD z a i b: NWD(8, 5) = NWD(5, 3) = NWD(3, 2) = NWD(2, 1) = NWD(1, 0) = 1 Ograniczenie zgodne z Tw. Gabriel Lamé: 5 ∗ 1 = 5 Ulepszone ograniczenie: 1 · ln(10)/ln(1.62) = 4, 77 Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 3 12 / 61 Złożoność czasowa NWD Przykład: Niech a = 55 a b = 34. Algorytm NWD wykonał 8 obrotów, aby obliczyć NWD z a i b: NWD(55, 34) = NWD(34, 21) = NWD(21, 13) = NWD(13, 8) = NWD(8, 5) = NWD(5, 3) = NWD(3, 2) = NWD(2, 1) = NWD(1, 0) = 1 Ograniczenie zgodne z Tw. Gabriel Lamé: 5 ∗ 2 = 10 Ulepszone ograniczenie: 2 · ln(10)/ln(1.62) = 2 · 4, 77 = 9, 54 Niech a = 89 a b = 55. Algorytm NWD wykonał 9 obrotów, aby obliczyć NWD z a i b: NWD(89, 55) = NWD(55, 34) = NWD(34, 21) = NWD(21, 13) = NWD(13, 8) = NWD(8, 5) = NWD(5, 3) = NWD(3, 2) = NWD(2, 1) = NWD(1, 0) = 1. Ograniczenie zgodne z Tw. Gabriel Lamé: 5 ∗ 2 = 10 Ulepszone ograniczenie: 2 · ln(10)/ln(1.62) = 2 · 4, 77 = 9, 54 Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 3 13 / 61 Złożoność czasowa NWD Przykład: Niech a = 144 a b = 55. Algorytm NWD wykonał 9 obrotów, aby obliczyć NWD z a i b: NWD(144, 55) = NWD(55, 34) = NWD(34, 21) = NWD(21, 13) = NWD(13, 8) = NWD(8, 5) = NWD(5, 3) = NWD(3, 2) = NWD(2, 1) = NWD(1, 0) = 1 Ograniczenie zgodne z Tw. Gabriel Lamé: 5 ∗ 2 = 10 Ulepszone ograniczenie: 2 · ln(10)/ln(1.62) = 2 · 4, 77 = 9, 54 Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 3 14 / 61 Liczby trójkatne ˛ Liczby trójkatne: ˛ 1, 3, 6, 10, 15, 21, itd.. n-ty element ciagu ˛ otrzymujemy poprzez dodanie liczby n do poprzedniego elementu ciagu, ˛ tj.: drugi element ciagu ˛ to 2 plus wartość pierwszego elementu (czyli 1), co daje 3. trzeci element ciagu ˛ to 3 plus 3 (wartość drugiego elementu), co daje 6; itd. Liczby trójkatne ˛ można przedstawić za pomoca˛ odpowiedniej ilości obiektów (kulek, pudełek, itp.) rozmieszczonych w formie trójkata: ˛ Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 3 15 / 61 Algorytm obliczajacy ˛ n-ta˛ liczbe˛ trójkatn ˛ a˛ Algorytm: triangle (n) 1: if n< 1 then 2: return 0; 3: end if 4: if n==1 then 5: return 1; 6: else 7: return n+ triangle(n - 1); 8: end if Bożena Woźna-Szcześniak (AJD) //wersja rekurencyjna int triangle (int n) { if (n<1) return 0; if (n==1) return 1; else return n+triangle(n-1); } //wersja iteracyjna int triangle2 (int n) { int total = 0; while (n>0) { total += n--; } return total; } Algorytmy i Struktury Danych. Wykład 3 16 / 61 Algorytm obliczajacy ˛ n-ta˛ liczbe˛ trójkatn ˛ a˛ Algorytm: triangle (n) 1: if n< 1 then 2: return 0; 3: end if 4: if n==1 then 5: return 1; 6: else 7: return n+ triangle(n - 1); 8: end if Bożena Woźna-Szcześniak (AJD) Ślad obliczeń triangle(4) triangle(3) triangle(2) triangle(1) return 1 return 2+1=3 return 3+3=6 return 4+6=10 Algorytmy i Struktury Danych. Wykład 3 17 / 61 Czasowa złożoność obliczeniowa T (n) - czas potrzebny do wykonania funkcji triangle (n) dla dowolnego wejścia o rozmiarze n. Przypadek bazowy: T (1) = 1 (jednostkowy czas pracy, gdy algorytm działa na wejściu wielkości 1); Krok indukcyjny: Dla wejścia o rozmiarze n, algorytm wykonuje prace˛ jednostkowa˛ realizujac ˛ operacje porównania, dodawania (tj. n + triangle(n − 1)) oraz zwrotu wartości, a nastepnie ˛ wywołuje sam siebie dla wejścia o rozmiarze n − 1. Zatem otrzymujemy nastepuj ˛ ace ˛ równanie: T (n) = T (n − 1) + 1 dla n > 0. Jeśli rozwiniemy rekurencje˛ otrzymujemy: T (0) = 1, T (1) = T (0) + 1 = 1 + 1 = 2 T (2) = T (1) + 1 = 2 + 1 = 3, T (3) = T (2) + 1 = 3 + 1 = 4 T (4) = T (3) + 1 = 4 + 1 = 5, . . ., T (n) = n + 1 Zatem T (n) = Θ(n). Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 3 18 / 61 Rekurencja - obliczanie an an = pow(a, n) = 1 a ∗ pow(a, n − 1) dla n = 0 dla n > 0 Ślad obliczeń long long pow(int a, int n) { if (n==0) return 1; else return a*pow(a,n-1); } Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. pow(2,3) pow(2,2) pow(2,1) pow(2,0) return 1. return 2*1 = 2 return 2*2 = 4 return 2*4 =8 Wykład 3 19 / 61 Czasowa złożoność obliczeniowa T (n) - czas potrzebny do wykonania funkcji pow(a,n) dla dowolnego wejścia o rozmiarze n. Przypadek bazowy: T (0) = 1 (jednostkowy czas pracy, gdy algorytm działa na wejściu wielkości 1); Krok indukcyjny: Dla wejścia o rozmiarze n, algorytm wykonuje prace˛ jednostkowa˛ realizujac ˛ operacje porównania, mnożenia (tj. a ∗ pow(a, n − 1)) oraz zwrotu wartości, a nastepnie ˛ wywołuje sam siebie dla wejścia o rozmiarze n − 1. Zatem otrzymujemy nastepuj ˛ ace ˛ równanie: T (n) = T (n − 1) + 1 dla n > 0. Jeśli rozwiniemy rekurencje˛ otrzymujemy: T (0) = 1, T (1) = T (0) + 1 = 1 + 1 = 2 T (2) = T (1) + 1 = 2 + 1 = 3, T (3) = T (2) + 1 = 3 + 1 = 4 T (4) = T (3) + 1 = 4 + 1 = 5, . . ., T (n) = n + 1 Zatem T (n) = Θ(n). Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 3 20 / 61 Ciag ˛ Fibonacciego Liczby naturalne tworzace ˛ ciag ˛ o takiej własności, że kolejny wyraz (z wyjatkiem ˛ dwóch pierwszych) jest suma˛ dwóch poprzednich nazywa sie˛ liczbami Fibonacciego. Poczatkowe ˛ wartości tego ciagu ˛ to: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, . . . Ciag ˛ Fibonacciego zawdziecza ˛ swoja˛ nazwe˛ włoskiemu matematykowi z Pizy, Leonardowi, który pod nazwiskiem Fibonacci wydał w 1202 roku słynna˛ ksieg ˛ e˛ Liber Abaci zawierajac ˛ a˛ opis tego ciagu ˛ jako rozwiazanie ˛ zadania o rozmnażaniu sie˛ królików. Ojciec Leonarda nosił przydomek Bonacci, stad ˛ syn został Fibonaccim (filius Bonacci - syn dobrotliwego). Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 3 21 / 61 Ciag ˛ Fibonacciego - rozmnażanie królików Zadanie Fibonacciego: Ile par królików może spłodzić jedna para w ciagu ˛ roku, jeśli: każda para rodzi nowa˛ pare˛ w ciagu ˛ miesiaca, ˛ para staje sie˛ płodna po miesiacu, ˛ króliki nie umieraja. ˛ Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 3 22 / 61 Ciag ˛ Fibonacciego - rozmnażanie królików Na poczatku ˛ – 1 para: Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 3 23 / 61 Ciag ˛ Fibonacciego - rozmnażanie królików Na poczatku ˛ – 1 para: W pierwszym miesiacu ˛ – ta sama 1 para (po 1 miesiacu ˛ króliki sa˛ zdolne do rozrodu): Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 3 23 / 61 Ciag ˛ Fibonacciego - rozmnażanie królików Drugi miesiac ˛ - para wydała na świat nowa˛ pare˛ królików. Sa˛ wiec ˛ - 2 pary królików Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 3 24 / 61 Ciag ˛ Fibonacciego - rozmnażanie królików Trzeci miesiac ˛ - stara para (w pionie) wydała na świat kolejna˛ pare˛ królików. Para młoda (po prawej) nie jest jeszcze płodna. Sa˛ teraz – 3 pary królików Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 3 25 / 61 Ciag ˛ Fibonacciego - rozmnażanie królików Czwarty miesiac ˛ - para środkowa wydała na świat kolejna˛ pare˛ królików. Para po prawej wydała na świat 1 pare, ˛ a para po lewej jeszcze nie jest gotowa do rozrodu. Zatem mamy - 5 par królików. Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 3 26 / 61 Ciag ˛ Fibonacciego - Złoty podział W wyniku podzielenia każdej z liczb ciagu ˛ przez jej poprzednik otrzymuje sie˛ iloraz oscylujacy ˛ wokół 1, 618 - liczby złotego podziału. W miare˛ zwiekszania ˛ sie˛ liczb zmniejszaja˛ sie˛ odchylenia od tej wartości. Dokładna wartość granicy jest złota˛ liczba: ˛ √ 5+1 = 1, 6180339887498948482... Φ= 2 Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 3 27 / 61 Ciag ˛ Fibonacciego - Złoty podział W wyniku podzielenia każdej z liczb ciagu ˛ przez jej poprzednik otrzymuje sie˛ iloraz oscylujacy ˛ wokół 1, 618 - liczby złotego podziału. W miare˛ zwiekszania ˛ sie˛ liczb zmniejszaja˛ sie˛ odchylenia od tej wartości. Dokładna wartość granicy jest złota˛ liczba: ˛ √ 5+1 = 1, 6180339887498948482... Φ= 2 ... 233/144 = 1.61805555556 144/89 = 1.61797752809 89/55 = 1.61818181818 55/34 = 1.61764705882 34/21 = 1.61904761905 21/13 = 1.61538461538 ... Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 3 27 / 61 Ciag ˛ Fibonacciego - Złoty podział W wyniku podzielenia każdej z liczb ciagu ˛ przez jej nastepnik ˛ otrzymuje sie˛ iloraz oscylujacy ˛ wokół 0, 618 - liczby złotego podziału. W miare˛ zwiekszania ˛ sie˛ liczb zmniejszaja˛ sie˛ odchylenia od tej wartości. Dokładna wartość granicy jest złota˛ liczba: ˛ √ 5−1 = 0, 618033989... Φ= 2 Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 3 28 / 61 Ciag ˛ Fibonacciego - Złoty podział W wyniku podzielenia każdej z liczb ciagu ˛ przez jej nastepnik ˛ otrzymuje sie˛ iloraz oscylujacy ˛ wokół 0, 618 - liczby złotego podziału. W miare˛ zwiekszania ˛ sie˛ liczb zmniejszaja˛ sie˛ odchylenia od tej wartości. Dokładna wartość granicy jest złota˛ liczba: ˛ √ 5−1 = 0, 618033989... Φ= 2 ... 144/233 = 0.618025751073 89/144 = 0.618055555556 55/89 = 0.61797752809 34/55 = 0.618181818182 21/34 = 0.617647058824 13/21 = 0.619047619048 ... Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 3 28 / 61 Ciag ˛ Fibonacciego - Złoty podział Złoty podział (łac. sectio aurea), podział harmoniczny, złota proporcja, boska proporcja (łac. divina proportio) - podział odcinka na dwie cz˛eści tak, by stosunek długości dłuższej z nich do krótszej był taki sam, jak całego odcinka do cz˛eści dłuższej. Φ= a a+b = a b Złotymi proporcjami wyznaczonymi na podstawie ciagu ˛ Fibonacciego posługiwał sie˛ w swoim malarstwie Leonardo da Vinci i Botticelli. Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 3 29 / 61 Ciag ˛ Fibonacciego - gdzie go można znaleźć ? Ciag ˛ Fibonacciego można odnaleźć w wielu aspektach przyrody, ciag ˛ taki opisuje np. liczbe˛ pedów ˛ rośliny jednostajnie przyrastajacej ˛ w latach. W słoneczniku możemy zaobserwować dwa układy linii spiralnych, wychodzacych ˛ ze środka. Liczba linii rozwijajacych ˛ sie˛ zgodnie z ruchem wskazówek zegara wynosi 55 i tylko 34 skreconych ˛ w przeciwna˛ strone. ˛ Takie same spirale można zaobserwować na wielu innych roślinach (np. kalafior, ananas). Liczby spiral wystepuj ˛ acych ˛ w tych roślinach sa˛ kolejnymi liczbami Fibonacciego. Źródło: http://www.math.edu.pl/liczby-fibonacciego Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 3 30 / 61 Ciag ˛ Fibonacciego - spirala 0 1 F (n) = f (n − 1) + f (n − 2) Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. if n = 0 if n = 1 if n ≥ 2 Wykład 3 31 / 61 Ciag ˛ Fibonacciego - algorytm rekurencyjny Definicja rekurencyjna: F (0) = 0, F (1) = 1 F (n) = F (n − 1) + F (n − 2), dla n ≥ 2 Algorytm: FIB (n) 1: if n == 0 or n == 1 then 2: return n; 3: end if 4: return FIB(n − 2) + FIB(n − 1); Złożoność obliczeniowa: Równanie opisujace ˛ zachowanie algorytmu: T (n) = T (n − 1) + T (n − 2) + Θ(1) dla n √> 1 oraz T (0) = T (1) = 1. Rozwiazanie ˛ T (n) = Θ(φn ), gdzie φ = 1+2 5 ≈ 1, 6 Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 3 32 / 61 Ciag ˛ Fibonacciego - drzewo wywołań F (5) F (4) F (2) F (1) F (3) F (3) F (0) F (2) F (1) Bożena Woźna-Szcześniak (AJD) F (1) F (2) F (1) F (1) F (0) F (0) Algorytmy i Struktury Danych. Wykład 3 33 / 61 Efektywność rekurencyjnego wykonania funkcji Fibonacciego n 6 10 15 20 25 30 Bożena Woźna-Szcześniak (AJD) Liczba dodawań 12 88 986 10 945 121 392 1 346 268 Liczba wywołań 25 177 1 973 21 891 242 785 2 692 537 Algorytmy i Struktury Danych. Wykład 3 34 / 61 Ciag ˛ Fibonacciego - algorytm iteracyjny Require: Liczba n {F0 , . . . , Fn−1 , Fn } Algorytm: FIB (n) 1: if n < 2 then 2: return n; 3: else 4: f 0 = 0; 5: f 1 = 1; 6: for i = 2 → n do 7: m = f 0 + f 1; 8: f 0 = f 1; 9: f 1 = m; 10: end for 11: end if 12: return m; Bożena Woźna-Szcześniak (AJD) Złożoność obliczeniowa: Θ(n) Algorytmy i Struktury Danych. Wykład 3 35 / 61 Efektywność iteracyjnego wykonania funkcji Fibonacciego n 6 10 15 20 25 30 Liczba przypisań algorytm iteracyjny 15 27 42 57 72 87 Bożena Woźna-Szcześniak (AJD) Liczba wywołań algorytm rekurencyjny 25 177 1 973 21 891 242 785 2 692 537 Algorytmy i Struktury Danych. Wykład 3 36 / 61 Wieże Hanoi Definicja problemu Dane: trzy pale A, B i C oraz N krażków ˛ o różnych średnicach. Warunki poczatkowe: ˛ Na jeden z pali, np. na A, nałożono krażki ˛ tak, że krażek ˛ mniejszy nie leży pod wiekszym. Pale B i C sa puste. Problem: Przenieść wszystkie krażki z pala A na C przy założeniu, że: można używać B jako pomocnicze miejsce przechowywania. nie można kłaść krażków ˛ wiekszych na mniejsze. Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 3 37 / 61 Wieże Hanoi - rozwiazanie ˛ rekurencyjne Ślad wykonania /* Przenosi n dyskow na lewo ( gdy left = true) lub prawo (gdy left = false) Wywolanie: moves(n, true); */ void moves(int n, bool left){ if (n == 0) return; moves(n-1, !left); if (left) cout<<n<< " left" << endl; else cout<<n<< " right"<<endl; moves(n-1, !left); } Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. moves(2, true) moves(1, false) moves(0, false) return; 1 right moves(0, true) return; 2 left moves(1, false) moves(0, true) return; 1 right moves (0,false) return; Wykład 3 38 / 61 Wieże Hanoi - wykonanie dla n = 2, 3, 4 1. 1 right 2. 2 left 3. 1 right Bożena Woźna-Szcześniak (AJD) 1. 2. 3. 4. 5. 6. 7. 1 2 1 3 1 2 1 left right left left left right left Algorytmy i Struktury Danych. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 1 2 1 3 1 2 1 4 1 right left right right right left right left right 2 left 1 right 3 right 1 right 2 left 1 right Wykład 3 39 / 61 Złożoność obliczeniowa Wież Hanoi T(n) - czas potrzebny do wykonania funkcji Hanoi(n) dla dowolnego wejścia o rozmiarze n. Algorytm rekurencyjny realizujacy ˛ problem Wież Hanoi (czyli przeniesienie n krażków ˛ z jednego palika na drugi z zachowaniem pewnych zasad) implikuje, że T (n) musi spełniać nastepuj ˛ ace ˛ równanie: T (n) = 2 · T (n − 1) + 1 dla n > 1 oraz T (1) = 1 Przykładowo: T (1) = 1, T (2) = 3, T (3) = 7, T (4) = 15. W ogólności: T (n) = 2n − 1 = Θ(2n ) Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 3 40 / 61 Wieże Hanoi - algorytm iteracyjny Niech A oznacza pal źródłowy, B pal pomocniczy, C pal docelowy oraz n bedzie ˛ liczba˛ dysków. 1 numOfMoves= pow(2,n)- 1. 2 if (n%2 == 0) then zamień miejscami pale $B$ i $C$. 3 for i = 1 to numOfMoves if (i%3 == 1) then przenieś górny dysk if i%3 == 2 then przenieś górny dysk if i%3 == 0 then przenieś górny dysk endfor do z A na C z A na B z B na C Złóżoność obliczeniowa: Θ(2n ) Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 3 41 / 61 Pułapki rekursji - brakujacy ˛ przypadek bazowy Ślad wykonania double H(int n) { return H(n-1) + 1.0/n; } Bożena Woźna-Szcześniak (AJD) H(4), H(3), H(2), H(1), H(0), (-1), ... Funkcja raz wywołana bedzie ˛ wywoływać siebie w nieskończoność. Algorytmy i Struktury Danych. Wykład 3 42 / 61 Pułapki rekursji - brak gwarancji konwergencji Ślad wykonania H(4), H(4), H(4), H(4), . . . double H(int n) { H(1) ⇒ return 1.0 if (n == 1) return 1.0; return H(n) + 1.0/n; Funkcja wywołana dla n = 1 zwróci } wartość 1 i zakończy sie, w każdym innym przypadku bedzie ˛ wywoływać siebie w nieskończoność. Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 3 43 / 61 Pułapki rekursji - wadliwy warunek bazowy Ślad wykonania long H (int n){ if (n == 1) return 1; else if (n % 2 == 0) return H(n-2)*n; else return H(n-1)*n; } Bożena Woźna-Szcześniak (AJD) H(1) ⇒ return 1 H(5), H(4), H(2), H(0), . . . H(6), H(4), H(2), H(0), . . . Funkcja wywołana dla n = 1 zwróci wartość 1 i zakończy sie, w każdym innym przypadku bedzie ˛ wywoływać siebie w nieskończoność. Algorytmy i Struktury Danych. Wykład 3 44 / 61 Pułapki rekursji - nadmierne wymagania pamieciowe ˛ double H(int n) { if (n == 0) return 0.0; return H(n-1) + 1.0/n; } Funkcja rekurencyjna H poprawnie oblicza n-ta˛ liczbe˛ harmoniczna. ˛ Jednakże, nie można jej używać dla dużych n, gdyż głebokość ˛ rekurencji jest proporcjonalna do n, a to powoduje przepełnienie stosu programu już przy n = 261897. Bożena Woźna-Szcześniak (AJD) double H1(int n) { double suma = 0.0; while (n!=0){ suma+= 1.0/n; n--; } return suma; } Funkcja nierekurencyjna H1 również poprawnie oblicza n-ta˛ liczbe˛ harmoniczna˛ imożna ja˛ stosować dla dużych n. Przykładowo, dla n = 500000000 Uzyskaliśmy wartość 20.6073 w czasie 1 sek. Algorytmy i Struktury Danych. Wykład 3 45 / 61 Fraktale Fraktale, czyli jak piekna ˛ może być matematyka i rekurencja ! Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 3 46 / 61 Zbiory Julii - Gaston Julia 1893 - 1978 F (0) = p; F (n + 1) = F (n)2 + c; gdzie: p - punkt płaszczyzny c - liczba zespolona bed ˛ aca ˛ parametrem zbioru. Dla różnych c otrzymujemy różne zbiory. Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 3 47 / 61 Zbiory Mandelbrota (fraktalne żółwie) F (0) = (0, 0); F (n + 1) = F (n)2 + c; gdzie: c - liczba zespolona bed ˛ aca ˛ parametrem zbioru. Dla różnych c otrzymujemy różne zbiory. Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 3 48 / 61 Fraktale Najstarsze fraktale wymyślili matematycy na poczatku ˛ XX-wieku, w wyniku zmagań z definicja˛ wymiaru i krzywej. Najwybitniejszym twórca˛ fraktali jest amerykański matematyk i informatyk polskiego pochodzenia - Benoit Mandelbrot. Na miedzynarodowym ˛ kongresie matematyków w Warszawie w roku 1983 stwierdził, że jest jeszcze za wcześnie na Źródło: http://en. formułowanie ścisłej definicji fraktala wikipedia.org/wiki/ ponieważ nie znamy dostatecznie Benoit_Mandelbrot głeboko ˛ istoty tego pojecia. ˛ Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 3 49 / 61 Czym jest fraktal? “Fraktalem jest wszystko...” Benoit Mandelbrot Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 3 50 / 61 Czym jest fraktal? “Fraktalem jest wszystko...” Benoit Mandelbrot Fraktal jest figura˛ geometryczna˛ o złożonej strukturze, nie bed ˛ aca ˛ krzywa, ˛ powierzchnia˛ ani bryła˛ w rozumieniu klasycznej matematyki; charakteryzuje ja˛ ułamkowy wymiar (stad ˛ nazwa fraktal -ang. ’fraction’ ułamek, łac. ’fractus’ złamany). Fraktale sa˛ bardzo skomplikowane. Dopiero komputery umożliwiły ich głebsze ˛ poznanie. Wielu badaczy twierdzi, że geometria fraktali jest geometria˛ przyrody. Fraktale dały poczatek ˛ nowej geometrii zwanej geometria˛ fraktalna, ˛ która pozwala modelować wiele obiektów i zjawisk wystepuj ˛ acych ˛ w przyrodzie i nie tylko ... Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 3 50 / 61 Cechy fraktali Fraktale maja˛ ceche˛ samopodobieństwa. Nie sa˛ określone wzorem matematycznym, tylko zależnościa˛ rekurencyjna. ˛ Sa˛ obiektami których wymiar nie jest liczba˛ całkowita. ˛ Każdy fraktal można w nieskończoność przybliżać. Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 3 51 / 61 Cechy fraktali Fraktale maja˛ ceche˛ samopodobieństwa. Nie sa˛ określone wzorem matematycznym, tylko zależnościa˛ rekurencyjna. ˛ Sa˛ obiektami których wymiar nie jest liczba˛ całkowita. ˛ Każdy fraktal można w nieskończoność przybliżać. Kalafior Bożena Woźna-Szcześniak (AJD) Brokuł Algorytmy i Struktury Danych. Drzewo Wykład 3 51 / 61 Zbiór Georga Cantora (1845 - 1918) Pierwsze fraktale powstały na przełomie XIX i XX wieku. Ich twórcami byli matematycy: Georg Cantor, David Hilbert, Helge von Koch oraz Wacław Sierpiński. Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 3 52 / 61 Zbiór Georga Cantora (1845 - 1918) Pierwsze fraktale powstały na przełomie XIX i XX wieku. Ich twórcami byli matematycy: Georg Cantor, David Hilbert, Helge von Koch oraz Wacław Sierpiński. W roku 1883 Georg Cantor zaproponował prosta˛ konstrukcje, ˛ w wyniku której otrzymuje sie˛ zbiór nazwany jego imieniem. Konstrukacja: Odcinek [0, 1] dzielimy na trzy równe cz˛eści i usuwamy środkowa. ˛ Z pozostałymi dwoma odcinkami postepujemy ˛ analogicznie. W konsekwencji takiego postepowania ˛ w granicy nieskończonej ilości kroków powstaje zbiór punktów Cantora. Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 3 52 / 61 Krzywa Kocha - Helge von Koch (1870 - 1924) W 1904 roku szwedzki matematyk Helge von Koch zaproponował konstrukcje˛ nazywana˛ potocznie płatkiem śniegu. Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 3 53 / 61 Krzywa Kocha 1 Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 3 54 / 61 Krzywa Kocha 1 2 Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 3 54 / 61 Krzywa Kocha 3 Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 3 55 / 61 Krzywa Kocha 3 4 Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 3 55 / 61 Krzywa Kocha 0) 1) 3) 4) Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. 2) Wykład 3 56 / 61 Dywan Sierpińskiego W 1916 roku Wacław Sierpiński (14.03.1882- 21.10.1969) rozszerzył zbiór Cantora na dwa wymiary. Kwadrat jednostkowy dzielimy na dziewieć ˛ i wyrzucamy środkowy. Postepujemy ˛ tak z każdym nowo powstałym kwadratem. Powstały fraktal nazywany dywanem Sierpińskiego. Analogicznie można postapić ˛ z trójkatem, ˛ którego boki dzielimy na dwie cz˛eści i powstałe punkty łaczymy ˛ co doprowadzi do powstania kolejnego trójkata, ˛ który usuwamy. Z pozostałymi trzema postepujemy ˛ podobnie, itd. Bożena Woźna-Szcześniak (AJD) Źródło:http: //www.gap-system. org/~history/ Biographies/ Sierpinski.html Algorytmy i Struktury Danych. Wykład 3 57 / 61 Dywan Sierpińskiego Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 3 58 / 61 Trójkat ˛ Sierpińskiego Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 3 59 / 61 Trójkat ˛ Sierpińskiego Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 3 60 / 61 Krzywa Hilberta Krzywa Hilberta - to przykład krzywej, która wypełnia całkowicie płaszczyzne, ˛ tzn. przechodzi przez wszystkie punkty płaszczyzny. Konstrukcja tej krzywej została podana przez Davida Hilberta w 1891 jako wariant krzywej Peano. n=1 n=2 Bożena Woźna-Szcześniak (AJD) n=3 Algorytmy i Struktury Danych. n=4 n=5 Wykład 3 61 / 61