pojęcia podstawowe. złożonośd czasowa algorytmów....
TRANSCRIPT
2010-10-13
1
Pojęcia podstawowe. Złożonośd czasowa algorytmów.
Rekurencja
Algorytmy i struktury danych
Wykład 1.
Rok akademicki: 2010/2011
2
Ramowy plan wykładów
• Pojęcie podstawowe.
• Poprawnośd i złożonośd algorytmów
• Rekurencja
• Algorytmy tablicowe
• Zbiory
• Tablice asocjacyjne
• Struktury listowe
• Drzewa
• Grafy
Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie
2010-10-13
2
3
Literatura
• Cormen T., Leiserson C., Rivest R., Stein C., Wprowadzenie do algorytmów, Wydawnictwo Naukowo-Techniczne, 2004
• Lafore R., Java. Algorytmy i struktury danych, Helion, 2004
• Koffman E., Wolfgang P., Struktury danych i techniki obiektowe na przykładzie Javy 5.0, Helion, 2006
• Wirth N., Algorytmy + struktury danych = programy, dowolne wydanie
• Sysło M., Algorytmy, Wydawnictwo Szkolne i Pedagogiczne, Warszawa, 1997
Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie
4
Informacje organizacyjne
• Wymiar godzinowy: 30 + 30
• Terminy zajęd: sroda, 13.05, s. 441 Budynek BG
• Egzamin: pisemny (nie ma zwolnieo z egzaminu)
• Materiały do wykładu: http://www.uek.krakow.pl/~lulap
Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie
2010-10-13
3
5
Algorytm
• sposób postępowania umożliwiający rozwiązanie zadania określonego typu
• podany w postaci zestawu kolejnych czynności do wykonania
• wykonawcą algorytmu może byd człowiek lub urządzenie (np. komputer)
Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie
6
Struktura danych
Zestaw powiązanych ze sobą danych wraz z mechanizmamiokreślającymi sposób tworzenia, likwidowania i wykorzystaniazdefiniowanego zestawu jako całości oraz poszczególnych jegoelementów.
Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie
2010-10-13
4
7
Program komputerowy
• zrozumiały dla komputera sposób zapisu algorytmu i opisu struktur danych
• zapisywany przy użyciu języków programowania.
Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie
Ewolucja metod programowania (1)
• Programowanie w języku maszynowym
– Programista posługuje się pojęciami charakterystycznymi dla systemu komputerowego, a nie dla dziedziny zastosowao (operuje rozkazami wchodzącymi w skład listy rozkazów procesora)
– Rozkazy składające się na program programista zapisu w postaci binarnych kodów
– Programista operuje bezpośrednio na komórkach pamięci operacyjnej. Odpowiedzialny jest za określenie sposobu binarnej reprezentacji informacji.
8Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie
2010-10-13
5
Ewolucja metod programowania (2)
• Programowanie w języku symbolicznym (asemblerze)– Programista posługuje się rozkazami
pochodzącymi z listy rozkazów procesora (ale są one zapisywane w postaci instrukcji, a nie w postaci binarnych kodów).
– Języki symboliczne wprowadziły zmiany w sposobie notacji programu, ale nie spowodowały zasadniczych zmian w zestawie pojęd wykorzystywanych do opisu algorytmów.
– Pojawiła się możliwośd przypisywania nazw komórkom pamięci (definiowanie zmiennych)
9Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie
Ewolucja metod programowania (3)
• Programowanie w językach wysokiego poziomu I generacji– Pojawiła się możliwośd stosowania instrukcji:
• podstawienia (przypisania), • warunkowej, • pętli (iteracji), • skoku.
– Przy opisie algorytmy następuje rezygnacja ze stosowania rozkazów z listy rozkazów procesora i pojawia się możliwośd stosowania pojęd o znacznie większym stopniu ogólności.
– Wprowadzenie mechanizmu deklarowania zmiennych
– Ułatwione zostało operowanie na wartościach tekstowych
– Pojawiła się możliwośd korzystania ze złożonych typów danych (tablice, pliki)
10Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie
2010-10-13
6
Ewolucja metod programowania (4)
• Programowanie proceduralne– Możliwośd definiowania podprogramów.
– Zdefiniowanie nowego podprogramu pozwala na rozszerzenie zbioru instrukcji dostępnych w stosowanym języku programowania.
– Mechanizm parametrów zwiększył uniwersalnośd definiowanych instrukcji.
– Pojawiła się możliwośd definiowania danych lokalnych (dostępnych tylko w podprogramie) oraz danych globalnych (dostępnych w całym programie)
11Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie
Ewolucja metod programowania (5)
• Programowanie strukturalne
– Zwiększenie liczby instrukcji sterujących (np.: różne postaci pętli, instrukcji warunkowych, wyboru, podstawienia) –dzięki czemu można było wyeliminowad instrukcję skoku bezwarunkowego
– Podział programu na dwie części: opis struktur danych i opis algorytmu
– Zwiększenie liczby dostępnych typów danych (tablice, rekordy, zbiory, pliki),
– Możliwośd stosowania dynamicznych struktur danych (stos, kolejka, listy, drzewa),
– Możliwośd definiowania własnych struktur danych.
12Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie
2010-10-13
7
Ewolucja metod programowania (6)
Programowanie obiektowe
• Równoległe definiowanie algorytmów i struktur danych i ich połączenie w jedną całośd(klasę):– reprezentuje w programie fragment rzeczywistości
(jego cechy, jego zachowania),
– pozwala programiście posługiwad się pojęciami charakterystycznymi dla dziedziny problemu (oderwad się od pojęd związanych ze sprzętem komputerowym),
– pozwala ukryd szczegóły implementacji
• klasa – abstrakcyjny typ danych (ABSTRAHOWANIE - operacja myślowa polegająca na uwzględnianiu tylko wybranych cech sytuacji (przedmiotu, osoby), z pominięciem cech uznanych za nieistotne)
13Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie
Wymagania wobec algorytmów
• poprawnośd – algorytm generuje prawidłowe rezultaty (nie zawiera błędów),
• wydajnośd – realizacja algorytmu wymaga użycia akceptowalnej ilości zasobów:– czasu,
– pamięci.
Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie 14
2010-10-13
8
15
Pojęcie błędu
• niezgodnośd z obowiązującymi regułami pisania, liczenia, wymowy itp.; odstępstwo od normy; pomyłka
• postępek, działanie, które przynosi komuś złe skutki; niewłaściwe posunięcie, przedsięwzięcie
• mylne, fałszywe mniemanie o czymś (przestarz.)
Źródło: Słownik języka polskiego PWN
Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie
16
Błędy w programowaniu
• błędy logiczne – na etapie projektowania algorytmu (środki zaradcze: stosowanie sprawdzonych algorytmów, formalne dowodzenie poprawności algorytmu, testowanie programu)
• błędy wykonania programu – ujawniające się w trakcie realizacji algorytmu zapisanego w postaci programu (ujawniające się w postaci wyjątków)
• błędy syntaktyczne – polegające na niezgodności tekstu programu z gramatyką języka programowania (wykrywane przez kompilator)
Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie
2010-10-13
9
17
Złożonośd obliczeniowa
• Złożonośd obliczeniowa algorytmu – ilośd zasobów systemu komputerowego niezbędnych do jego realizacji.
• Zasoby systemu komputerowego niezbędne do realizacji algorytmu:
– czas pracy procesora (złożonośd czasowa algorytmu),
– pamięd operacyjna (złożonośd pamięciowa algorytmu).
• Złożonośd obliczeniowa jest uzależniona od wielkości zadania.
Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie
18
Sortowania przez wybieranie (1)
import java.io.*;
public class SortowaniePrzezWybieranie static void sortuj(int [] liczby)
int k, pomoc;for (int i = 0; i < liczby.length - 1; i++)
k = i;for (int j = i; j < liczby.length; j++)
if (liczby[k] > liczby[j])k = j;
pomoc = liczby[i];liczby[i] = liczby[k];liczby[k] = pomoc;
Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie
2010-10-13
10
19
Sortowania przez wybieranie (2)
static int czytajLiczbe() throws IOException
BufferedReader klaw = new BufferedReader (new
InputStreamReader (System.in));
return Integer.parseInt(klaw.readLine());
static void drukujWektor(int [] tab)
for (int i = 0; i < tab.length; i++)
System.out.print(tab[i] + " ");
System.out.print("\n");
Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie
20
Sortowania przez wybieranie (3)
public static void main(String [] args) throws IOException System.out.print("Liczba elementow w wektorze: ");int n = czytajLiczbe();
int [] wektor = new int[n];
for (int i = 0; i < wektor.length; i++)wektor[i] = (int) (100 * Math.random());
long czas1, czas2;czas1 = System.currentTimeMillis();// czas w milisekundach, jaki upłynął od // 1 stycznia 1970 roku, godz. 0:00
sortuj(wektor);czas2 = System.currentTimeMillis();System.out.println("Czas realizacji obliczen: " + (czas2 - czas1));
Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie
2010-10-13
11
21
Sortowania przez wybieranie (4)
Rezultat działania programu:
Liczba elementow w wektorze: 10000
Czas realizacji obliczen: 250
Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie
22
Czas realizacji algorytmu (1)
Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie
2010-10-13
12
23
Czas realizacji algorytmu (2)
Czas (milisekundy)
0
20000
40000
60000
80000
100000
120000
0 50000 100000 150000 200000 250000
y = 0,000002 n2 – 0,0094 n + 286,41
Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie
Oszacowanie czasu realizacji algorytmu (1)
24Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie
2010-10-13
13
Oszacowanie czasu realizacji algorytmu (2)
• Analiza powyższych danych pozwala stwierdzid, że czas obliczeo uzależniony jest przede wszystkim od składnika:
0,000002 n2
Składnik ten nazywany jest składnikiem dominującym.
• Po pominięciu stałych współczynników można stwierdzid, że zależnośd pomiędzy czasem wykonania a wielkością zadania ma charakter funkcji kwadratowej. Kwadratowy charakter zależności uwidacznia się w coraz większym stopniu wraz ze wzrostem wielkości zadania.
25Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie
Cechy empirycznego określania złożoności
• Zalety:– otrzymane czasy obliczeo są proste w interpretacji
• Wady:– koniecznośd wielokrotnego uruchamiania programu (dla złożonych algorytmów
może to byd bardzo czasochłonne),– uzyskane wyniki dotyczą zastosowanego w obliczeniach zestawu danych (trudno
jest określid czas realizacji dla przypadku „najlepszego”, najgorszego” oraz „przeciętnego”),
– wyniki dotyczą zwykle stosunkowo niewielkich zbiorów danych – nie wiadomo, czy dla zbiorów o większym rozmiarze charakter zależności się nie zmieni,
– czas jest uzależniony od szybkości i architektury komputera, języka programowanie, techniki translacji, systemu operacyjnego – trudna porównywalnośd wyników
– z uwagi na wielozadaniowy charakter systemów operacyjnych trudno jest określid, jaka częśd czasu była rzeczywiście przeznaczona na realizację analizowanego programu.
26Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie
2010-10-13
14
27
Bezpośrednia analiza algorytmów
Analiza dotyczy:
• charakteru zależności (np. zależnośd liniowa lub kwadratowa), a nie jej dokładnej postaci (wzór funkcji) – uwzględniany jest element dominujący, pomijane są współczynniki stałe
• górnego i dolnego ograniczenia czasu realizacji algorytmu (a nie czasu realizacji algorytmu)
– górne ograniczenie – czas realizacji algorytmu jest nie większy niż ... (ale może byd krótszy) – przypadek pesymistyczny,
– dolne ograniczenie – czas realizacji algorytmu jest nie mniejszy niż ... (ale może byd dłuższy) – przypadek optymistyczny,
• zachowania się algorytmu dla zbiorów danych o dużej wielkości (czyli dla wszystkich n większych od pewnej wartości n0)
Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie
Górne ograniczenie czasu realizacji algorytmu (1)
• f(n) – czas realizacji algorytmu (zależny od n)
• f(n) zależy od wielu czynników i podanie dokładnego charakteru zależności jest trudne
• łatwiej jest zdefiniowad ograniczenie górne dla f(n).
28
f(n)
n
c g(n)
Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie
2010-10-13
15
Górne ograniczenie czasu realizacji algorytmu (2)
• Czas realizacji algorytmu jest rzędu co najwyżej g(n), jeśli istnieją stała rzeczywista c > 0 i stała naturalna n0 takie, że nierównośd f(n) ≤ c g(n) zachodzi dla każdego n ≥ n0.
• Zbiór wszystkich funkcji f(n) spełniających powyższe ograniczenie określany jest jako O(g(n)).
• O(g(n)) = f(n): istnieją dodatnie stałe c oraz n0 takie, że 0 ≤ f(n) ≤ c g(n) dla wszystkich n ≥ n0
29Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie
Górne ograniczenie czasu realizacji algorytmu (3)
Stwierdzenie:
czas realizacji algorytmu wynosi O(g(n))
lub
czas realizacji algorytmu jest rzędu co najwyżej g(n)
lub
algorytm jest klasy O(g(n))
oznacza: że istnieje taka stała c, że dla n ≥ n0 czas realizacji algorytmu wynosi co najwyżej c g(n).
30Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie
2010-10-13
16
Dolne ograniczenie czasu realizacji algorytmu (4)
• Czas realizacji algorytmu jest rzędu co najmniej g(n), jeśli istnieją stała rzeczywista c > 0 i stała naturalna n0 takie, że nierównośd f(n) ≥ c g(n)zachodzi dla każdego n ≥ n0.
• Zbiór wszystkich funkcji spełniających to ograniczenie określany jest jako Ω(g(n))
• Ω(g(n)) = f(n): istnieją dodatnie stałe c i n0 takie, że 0 ≤ cg(n) ≤ f(n) dla wszystkich n ≥ n0
31
f(n)
n
c g(n)
Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie
Dolne i górne ograniczenie czasu realizacji algorytmu (1)
• Czas realizacji algorytmu jest dokładnie rzędu g(n) jeśli istnieją stała rzeczywista c1 > 0, c2 > 0 i stała naturalna n0 takie, że nierównośd c1 g(n) ≤ f(n) ≤ c2 g(n) zachodzi dla każdego n ≥ n0.
32
f(n)
n
c1 g(n)
c2 g(n)
Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie
2010-10-13
17
Dolne i górne ograniczenie czasu realizacji algorytmu (2)
• Zbiór wszystkich funkcji spełniających to ograniczenie określany jest jako Θ(g(n))
• Θ(g(n)) = f(n); istnieją dodatnie stałe c1, c2 i n0 takie, że 0 ≤ c1
g(n) ≤ f(n) ≤ c2 g(n) dla wszystkich n ≥ n0
33Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie
34
Średnia złożonośd obliczeniowa
• Średnia złożonośd czasowa uwzględnia prawdopodobieostwa pojawienia się każdego możliwego zestawu danych wejściowych
• Zi(n) – i-ty możliwy zestaw danych n-elementowy
• pi – prawdopodobieostwo wystąpienia i-tego zestawu
• Ti(n) – złożonośd czasowa algorytmu dla i-tego zestawu danych
• Średnia złożonośd czasowa algorytmu dana jest formułą:
i
iiśr nTpnT
Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie
2010-10-13
18
Złożonośd obliczenia sortowania przez wybieranie (1)
static void sortuj(int [] liczby) int k, pomoc;for (int i = 0; i < liczby.length - 1; i++)
//koszt K1k = i;for (int j = i; j < liczby.length; j++)
//koszt K2if (liczby[k] > liczby[j])
k = j;//koszt K3pomoc = liczby[i];liczby[i] = liczby[k];liczby[k] = pomoc;
35Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie
Złożonośd obliczenia sortowania przez wybieranie (2)
for (int i = 0; i < n - 1; i++)
K1
for (int j = i; j < n; j++)
K2
K3
36Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie
2010-10-13
19
Złożonośd obliczenia sortowania przez wybieranie (3)
for (int i = 0; i < n - 1; i++)
K1
(n – 1) * K2
K3
37Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie
Złożonośd obliczenia sortowania przez wybieranie (4)
(n – 1) * K1 + (n – 1) [n * K2 + (n-1) * K2 + ... + 2 * K2] + (n – 1) * K3 =
= n * K1 – K1 + *½ * (2 + n) * (n – 1) * K2] + n * K3 – K3 =
= n * K1 – K1 + n * K2 – K2 + ½ * n2 * K2 – ½ * n * K2 + n * K3 –K3 =
= ½ * K2 * n2 + (K1 + ½ * K2 + K3) * n – (K1 + K2 + K3) = O(n2)
38Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie
2010-10-13
20
39
Rodzaje złożoności (1)
• Złożoność logarytmiczna – log n
• W każdym kroku algorytmu zadanie o rozmiarze n jest sprowadzane do zadania o rozmiarze n / 2
• Przykład:
• algorytm wyszukiwania binarnego jest klasy O(log n)
• Przykładowa realizacja wyszukiwania binarnego: Mamy odszukad wartośd 11 w ciągu liczb:
1, 2, 7, 9, 9, 11, 12, 15, 22, 34, 52, 67, 87, 90, 99
1, 2, 7, 9, 9, 11, 12
9, 11, 12
Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie
40
Rodzaje złożoności (2)
• Złożoność liniowa – n
• gdy dla każdego elementu pochodzącego z n – elementowego zbioru danych wykonywana jest stała liczba operacji
• Przykłady:– wyszukiwanie sekwencyjne
– sumowanie liczb w wektorze
– wyznaczanie minimum, maksimum
Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie
2010-10-13
21
41
Rodzaje złożoności (3)
• złożoność liniowo – logarytmiczna – n log n
• gdy w każdym kroku zadanie o rozmiarze n jest sprowadzane do dwóch zadao o rozmiarze n/2, a uzyskane wyniki są ponownie scalane
• Przykład:
– sortowanie przez łączenie jest klasy O(n log n)
– sortowanie szybkie – jest klasy O(n2), ale przeciętny czas realizacji algorytmu jest rzędu n log n
Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie
42
Rodzaje złożoności (4)
• złożoność kwadratowa – n2
• gdy dla każdej pary elementów realizowana jest pewna, stała liczba operacji (zwykle algorytmy takie są zapisywane za pomocą dwóch zagnieżdżonych pętli for)
• Przykłady:– proste metody sortowania (przez wstawianie, wybieranie, bąbelkowe)
są klasy O(n2), również średni czas realizacji tych metod jest rzędu O(n2)
Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie
2010-10-13
22
43
Rodzaje złożoności (5)
• złożoność wielomianowa stopnia wyższego niż dwa (n3, n4, ...)
• Przykład:
• mnożenie macierzy w sposób tradycyjny jest algorytmem klasy O(n3)
Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie
44
Rodzaje złożoności (6)
• Złożoność wykładnicza postaci 2n
• gdy realizowanych jest n kroków, a liczba operacji w każdym z nich wzrasta w sposób geometryczny
• Przykład:– wieże Hanoi
Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie
2010-10-13
23
45
Rodzaje złożoności (7)
• Złożoność wykładnicza typu n!
• gdy pewna, stała liczba operacji realizowana jest dla każdej permutacji n elementów
• Przykład:
• Tworzenie magicznych kwadratów z n elementów (pierwiastek z n musi byd wartością całkowitą)
• Algorytm postępowania: tworzymy kolejną permutację, wpisujemy do kwadratu i sprawdzamy, czy spełnia konieczne warunki.
Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie
46
Rodzaje złożoności (8)
Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie
2010-10-13
24
47
Rekurencja
• Rekurencyjny sposób zapisu kodu programu - z poziomu podprogramu wywoływany jest ten sam podprogram.
48
Przykład (1)
public class Rekurencja01
static void f()
System.out.println("Poczatek");
f();
System.out.println("Koniec");
public static void main(String [] args)
f();
2010-10-13
25
49
Przykład (2)
Początek
f(x)
Koniec
Początek
f(x)
Koniec
Początek
f(x)
Koniec
Początek
f(x)
Koniec
main()
f()
i.t.d.
50
Przykład (3)
Efekt uruchomienia programu:
Poczatek
Poczatek
Poczatek
....
Poczatek
Exception in thread "main"
java.lang.StackOverflowError
2010-10-13
26
51
Warunek stopu
• Wywołania rekurencyjne muszą się zakooczyd (w podprogramie musi zostad zdefiniowany warunek zatrzymania się algorytmu /warunek stopu/).
52
Przykład (1)
public class Rekurencja02 static int licznik = 0;static void f()
licznik++;System.out.println("Poczatek");if (licznik <=5) f();System.out.println("Koniec");
public static void main(String [] args)
f();
2010-10-13
27
53
Przykład (2)
licznik = 1
Początek
f(x)
Koniec
licznik = 2
Początek
f(x)
Koniec
licznik = 3
Początek
f(x)
Koniec
licznik = 4
Początek
f(x)
Koniec
licznik = 5
Początek
f(x)
Koniec
main()
f()
licznik = 6
Początek
Koniec
54
Przykład (3)
Efekt uruchomienia programu:
Poczatek
Poczatek
Poczatek
Poczatek
Poczatek
Poczatek
Koniec
Koniec
Koniec
Koniec
Koniec
Koniec
2010-10-13
28
55
Rekurencyjne obliczanie silni (1)
public class Rekurencja03 static int silnia(int n)
int pomoc;System.out.println("Wywolanie: silnia(" + n + ")");if ((n == 0) || (n == 1)) pomoc = 1;else pomoc = n * silnia(n-1);System.out.println("Zwrocenie wyniku: " + n + "! = " + pomoc);return pomoc;
public static void main(String [] args) System.out.println("4! = " + silnia(4));
56
Rekurencyjne obliczanie silni (2)
2010-10-13
29
57
Rekurencja może byd kosztowna ...
public class Rekurencja04 static int licznik = 0;static int fib(int n)//obliczanie n-tej liczby Fibonacciego
licznik++;if (n == 0) return 0;else
if (n == 1) return 1;else return fib(n-1) + fib(n-2);
public static void main(String [] args) System.out.println("5-ta liczba Fibonacciego to: " + fib(5));System.out.println("Liczba wywolan funkcji:" + licznik);
58
Efekt działania:
5-ta liczba Fibonacciego to: 5
Liczba wywolan funkcji: 15
2010-10-13
30
Sposób wyznaczania liczb Fibonacciego
59
Jeśli istnieje oczywiste rozwiązanie iteracyjne, to należy je wybrad.
Sterowanie kolejnością wykonywania działao (1)
public class Rekurencja05 static void sekwencja(int n)
System.out.print(n + " ");if (n > 0) sekwencja(n-1);
public static void main(String [] args)
sekwencja(5);System.out.println();
Efekt działania programu:5 4 3 2 1 0
60
2010-10-13
31
Sterowanie kolejnością wykonywania działao (2)
public class Rekurencja06 static void sekwencja(int n)
if (n > 0) sekwencja(n-1);System.out.print(n + " ");
public static void main(String [] args)
sekwencja(5);System.out.println();
Efekt działania programu0 1 2 3 4 5
61
62
Wieże Hanoi
public class Rekurencja08 static void przesun(int ile, char wiezaZrodlowa, char wiezaDocelowa, char wiezaPomocnicza)
if (ile == 1)System.out.println(wiezaZrodlowa + " => " + wiezaDocelowa);
else
przesun(ile-1,wiezaZrodlowa,wiezaPomocnicza,wiezaDocelowa);
System.out.println(wiezaZrodlowa + " => " +wiezaDocelowa);
przesun(ile-1,wiezaPomocnicza,wiezaDocelowa,wiezaZrodlowa);
2010-10-13
32
63
Złożonośd algorytmu: Wieże Hanoi (1)
• Analizowana jest liczba przesunięd potrzebna do rozwiązania zadania z n krążkami (liczbę przesunięd oznaczymy przez P(n))
• gdy n = 1 to P(1) = 1
• gdy n > 1 to P(n) = 2 * P(n – 1) + 1
64
Złożonośd algorytmu: Wieże Hanoi (2)
P(n-3) P(n-3) P(n-3) P(n-3) P(n-3)P(n-3)P(n-3)P(n-3)1 1 11
P(n-2) P(n-2) P(n-2) P(n-2)1 1
P(n-1) P(n-1)1
P(n)
Liczba
przesunięć
1
2
4
Poziom
0
1
2
3
2010-10-13
33
65
Złożonośd algorytmu: Wieże Hanoi (3)
• P(n) = P1 + P2 + P3 + ... + Pn = 2n – 1
• W powyższym wzorze zastosowany został wzór na sumę npierwszych elementów ciągu geometrycznego (o elementach b1, b2, ..., bn i ilorazie q)
• Sn = b1 * (qn – 1) / (q – 1)
Inwersja elementów w wektorze (1)
public class Rekurencja07
static void wyswietlWektor(int [] w)
for(int i = 0; i < w.length; i++)
System.out.print(w[i] + " ");
System.out.println();
66
2010-10-13
34
Inwersja elementów w wektorze (2)
static void inwersja(int poczatek, int koniec, int [] w)
if (poczatek < koniec)
int pomoc = w[poczatek];
w[poczatek] = w[koniec];
w[koniec] = pomoc;
inwersja(poczatek+1,koniec-1,w);
67
Inwersja elementów w wektorze (3)
public static void main(String [] args)
int [] tab = 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11;
wyswietlWektor(tab);
inwersja(0,tab.length-1,tab);
wyswietlWektor(tab);
Efekt działania programu:
1 2 3 4 5 6 7 8 9 10 11
11 10 9 8 7 6 5 4 3 2 1
68
2010-10-13
35
69
Sortowanie szybkie (1)
• Hoare, 1960
void quickSort(int tab[], int first, int last)
• wybierz jedną z wartości znajdujących się w wektorze (w poniższym algorytmie wybierana jest wartośd znajdująca się na pozycji o numerze first)
• dokonaj przemieszczenia elementów w wektorze, tak aby uzyskad:
elementy < x | x | elementy >= x• za pomocą tej samej procedury uporządkuj częśd wektora
znajdującą się na lewo od wartości „x” oraz częśd znajdującą się na prawo od wartości „x”.
• średnia złożonośd obliczeniowa: O(n * log(n))• pesymistyczna złożonośd obliczeniowa O(n2)
70
Sortowanie szybkie (2)
public class QuickSort
public static void swap (int tab[], int x, int y)
int temp = tab[x];
tab[x] = tab[y];
tab[y] = temp;
2010-10-13
36
71
Sortowanie szybkie (3)
public static int partition(int tab[], int first, int last)
int pivot = tab[first]; int up = first;int down = last;
do while ((up < last) && (pivot >= tab[up])) up++;while (pivot < tab[down]) down--;if (up < down) swap(tab,up,down); while (up < down);
swap(tab,first,down);
return down;
72
Sortowanie szybkie (4)
public static void quickSort(int tab[], int first,
int last)
if (first >= last) return;
int pivot = partition(tab, first, last);
quickSort(tab, first, pivot-1);
quickSort(tab, pivot+1, last);
2010-10-13
37
73
Sortowanie szybkie (5)
public static void main(String argv[]) int n = 10;
int tab[] = new int[n];for (int i=0 ; i < n; i++)
tab[i] = (int) (100 * Math.random());
quickSort(tab, 0, n-1);
for (int i=0 ; i < n; i++) System.out.print(tab[i] + " ");
System.out.println();
Sortowanie przez łączenie – Mergesort (1)
• sort(int poczatek, int koniec, int [] w),
• podziel wektory na dwie połowy,
• posortuj każdą z nich (za pomocą tej samej metody, o ile ich długośd > 1),
• połącz posortowane części w całośd,
• złożonośd obliczeniowa: O(n * log(n)).
74
2010-10-13
38
Sortowanie przez łączenie – Mergesort (2)
public class MergeSort
static void wyswietlWektor(int [] w)
for(int i = 0; i < w.length; i++)
System.out.print(w[i] + " ");
System.out.println();
75
Sortowanie przez łączenie – Mergesort (3)
static void sort(int poczatek, int koniec, int [] w)
if (poczatek >= koniec) return;
int srodek = (poczatek + koniec) / 2;
sort(poczatek, srodek, w);sort(srodek+1, koniec, w);
scal(poczatek, srodek, koniec, w);
76
2010-10-13
39
Sortowanie przez łączenie – Mergesort (3)
static void scal(int poczatek, int srodek, int koniec, int [] w) int pocz1 = poczatek; int kon1 = srodek;int pocz2 = srodek + 1;int kon2 = koniec;
while ((pocz1 <= kon1) && (pocz2 <= kon2)) if (w[pocz1] < w[pocz2]) pocz1++;else
int pomoc = w[pocz2];for (int i = pocz2 - 1; i >= pocz1; i--)
w[i+1] = w[i];w[pocz1] = pomoc;
pocz1++;kon1++;pocz2++;
77
Sortowanie przez łączenie – Mergesort (4)
public static void main(String [] args)
int [] tab = 1, 5, 3, 7, 7, 9, 2, 3, 2, 2, 3;wyswietlWektor(tab);sort(0,tab.length-1,tab);wyswietlWektor(tab);
Wynik działania programu1 5 3 7 7 9 2 3 2 2 31 2 2 2 3 3 3 5 7 7 9
78