Podstawy Informatyki Sprawność algorytmów
Sprawność algorytmów Kryteria oceny oszczędności Miara złożoności rozmiaru pamięci (złożoność pamięciowa): Liczba zmiennych + liczba i rozmiar struktur danych w algorytmie Miara czasu wykonania (złożoność czasowa) Liczba elementarnych akcji wykonanych przez procesor w trakcie wykonania algorytmu Ulepszenia wprowadzone post factum modyfikacja programu przez przeniesienie instrukcji ze środka na zewnątrz pętli Przykład 1 max = maksimum(t); //zwraca największą wartość w tablicy t for(i=0; i<100; i++) t[i] = t[i]*100/max; po ulepszeniu: max = maksimum(t); //zwraca największą wartość w tablicy t wspol = 100/max; for(i=0; i<100; i++) t[i] = t[i]*wspol;
Ulepszenia post factum Przykład 2 Przed: Wyszukanie w liście liniowej L elementu o wartości x. Prosty algorytm zawiera warunek postaci: 1. czy znaleziono w L wartość x i 2. czy został osiągnięty koniec listy L? Po ulepszeniu: Na koniec listy dodawany jest element o wartości x. Wyszukiwanie sprowadza się tylko do sprawdzania warunku 1.
Ulepszenia rzędu wielkości Problem wyszukiwania elementu w posortowanej liście L o długości N. Algorytm A: y = pierwszy_element_listy(l); while((y rozne od x) i (nie osiągnięto końca listy L)){ y = weź_następny_element_listy(l); } Algorytm A, w najgorszym przypadku wykona się w czasie rzędu N. Algorytm wykonuje się w czasie O(N) notacja duże-o, tzn., że stała liczba K taka, że algorytm wykona się w czasie nie dłuższym niż K*N w najgorszym przypadku. Czas wykonania algorytmu rośnie liniowo z N. Notacja duże-o jest pesymistycznym oszacowaniem czasy wykonania algorytmu.
Ulepszenia rzędu wielkości Wyszukiwanie binarne dla problemu wyszukiwania elementu w posortowanej liście L o długości N. start Weź całą listę L nie Czy x = L[długość_listy/2]? tak Wypisz znaleziono x Weź pierwszą lub drugą połowę listy, w zależności od wyniku porównania nie Czy rozważana lista jest pusta? tak Wypisz w liście L nie ma elementu o wartości x stop Policzenie porównań. Każde porównanie skraca długość listy wejściowej o połowę. Proces ten kończy się, gdy lista jest pusta lub gdy znaleziony zostanie poszukiwany element. Pesymistyczna liczba porównań = ile razy wielkość N można podzielić przez 2, zanim osiągnie 0, czyli log 2 N, a w rzeczywistości redukuje się N do 1, więc 1+log 2 N.
Ulepszenia rzędu wielkości wyszukiwanie binarne Porównanie liczby porównań dla wyszukiwania elementu w posortowanej liście o długości L dla dwóch algorytmów: prostego wyszukiwania binarnego N 1+ log 2 N 10 4 100 7 1000 10 milion 20 miliard 30 miliard miliardów 60 Czy wystarczy policzyć porównania? W algorytmie wyszukiwania binarnego wszystkie operacje oprócz porównań nie przekraczają pewnej stałej całkowita liczba instrukcji wykonywanych przez algorytm dla listy o długości N nie przekracza: K + (K 2 *log 2 N) złożoność pesymistyczna jest równa O(log 2 N).
Rzędy wielkości funkcji Rzędy wielkości funkcji Rząd wielkości funkcji opisuje czas działania algorytmu charakteryzuje efektywność algorytmu za jego pomocą można porównać różne algorytmy Asymptotyczna złożoność algorytmu określenie rzędu wielkości czasu działania algorytmu, tzn. określenie szybkości wzrostu czasu działania algorytmu, gdy rozmiar danych dąży do nieskończoności. Notacja asymptotyczna W notacji asymptotycznej czas działania algorytmów opisywany jest przez funkcje określone na zbiorze liczb naturalnych ℵ. Argument funkcji jest najczęściej rozmiarem danych wejściowych.
Notacja asymptotyczna Notacja Θ Dla danej funkcji g(n) oznaczamy przez Θ(g(n)) zbiór funkcji: Θ(g(n)) = {f(n): stałe c 1, c 2 > 0 i n 0 ℵ + : c 1 g(n) f(n) c 2 g(n) n n 0 } Notacja Θ jest asymptotycznie dokładnym oszacowaniem; ogranicza funkcję od góry i od dołu. Przykład Dana jest funkcja kwadratowa f(n) = an 2 + bn + c, gdzie a, b, c są stałymi i a > 0. Odrzucając składniki niższego rzędu otrzymujemy f(n) = Θ(n 2 ). Wynika to z faktu, że: c 1 = a/4; c 2 = 7a/4 n 0 = 2 * max( b /a, sqrt( c /a)) Notacja O Dla danej funkcji g(n) oznaczamy przez O(g(n)) zbiór funkcji: O(g(n)) = {f(n): stałe c > 0 i n 0 ℵ + :0 f(n) cg(n) n n 0 } Notacja O jest asymptotyczną granicą górną; szacuje pesymistyczny czas działania algorytmu. Θ(g(n)) O(g(n))
Notacja asymptotyczna Notacja Ω Dla danej funkcji g(n) oznaczamy przez Ω(g(n)) zbiór funkcji: Ω(g(n)) = {f(n): stałe c > 0 i n 0 ℵ + :0 cg(n) f(n) n n 0 } Notacja Ω jest asymptotyczną granicę dolną; oszacowuje czas działania algorytmu dla najlepszego przypadku Twierdzenie Dla każdych dwóch funkcji f(n) i g(n) zachodzi zależność f(n) = Θ(g(n)) f(n) = O(g(n)) i f(n) = Ω(g(n)) c 1 g(n) c g(n) f(n) f(n) f(n) c 2 g(n) cg(n) n 0 n n 0 n n 0 n
Notacja asymptotyczna Własności funkcji Założenie: funkcje f(n) i g(n) są asymptotycznie dodatnie Przechodniość f(n) = Θ(g(n)) g(n) = Θ(h(n)) f(n) = Θ(h(n)) f(n) = O(g(n)) g(n) = O(h(n)) f(n) = O(h(n)) f(n) = Ω(g(n)) g(n) = Ω(h(n)) f(n) = Ω(h(n)) Zwrotność f(n) = Θ(f(n)) f(n) = O(f(n)) f(n) = Ω(f(n)) Symetria f(n) = Θ(g(n)) g(n) = Θ(f(n)) Symetria transpozycyjna f(n) = O(g(n)) g(n) = Ω(f(n))
Analiza kosztu czasowego Analiza kosztu czasowego zagnieżdżonych pętli Przykład Algorytm sortowania bąbelkowego pętla zewnętrzna (1) wykona się N-1 razy pętla wewnętrzna (2) wykona się też N-1 razy koszt czasowy algorytmu: T(N) = (N-1)*(N-1) = N 2 2N 1 O(N 2 ) for i=1 to N 1 do{ //(1) x pierwszy element; for j=2 to N do{ //(2) if (x > element o numerze j) zamień te elementy miejscami; x element o numerze j; } } Analiza kosztu czasowego rekurencji Przykład Poszukiwanie najmniejszego i największego elementu w nieuporządkowanej liście L Niech T(N) pesymistyczna liczba porównań funkcji Znajdź_min_max dla listy o długości N. Wtedy: 1. Jeśli N=1, to T(1)=0 2. Jeśli N=2, to T(2)=2 2. Jeśli N>2, to T(N)=2*T(N/2)+2 koszt czasowy algorytmu O(N) struktura minmax{ element_listy min, max; }; minmax Znajdź_min_max(lista L){ minmax wynik,wynik1,wynik2; if(dlugosc_listy(l)==1){ wynik.min wynik.max L[1]; return wynik; } podziel_liste(l,l 1,L 2 ); //podziel listę L //na połowy L 1 o L 2 wynik1 Znajdź_min_max(L 1 ); wynik2 Znajdź_min_max(L 2 ); wynik.min minimum(wynik1.min, wynik2.min); wynik.max maximum(wynik1.max, wynik2.max); return wynik; }
Dolne i górne ograniczenia Dolne i górne ograniczenia Znalezienie algorytmu rozwiązania danego problemu ustanawia górne ograniczenie dla tego zadania algorytmicznego. Jeżeli dolne i górne ograniczenie są sobie równe z dokładnością do stałych, to problem w sensie notacji O( ) jest zamknięty. algorytm dla P o złożoności O(N 3 )... algorytm dla P o złożoności O(N 2 ) górne ograniczenia P problem algorytmiczny P złożoność obliczeniowa P? dowód, że koszt P jest równy O(N*logN) dowód, że koszt P jest równy O(N) dolne ograniczenia P Przykład problemu, który nie jest zamknięty. Problem minimalnego drzewa rozpinającego. Udowodniono, że zadanie to wymaga O(N) czasu, gdzie N jest liczbą krawędzi w grafie, ale nie ma algorytmu, który realizowałby to zadanie w czasie liniowym.