ASD - ukochane
Algorytm poprawny cz臋艣ciowo - (dla dowolnych danych wej艣ciowych i dowolnych danych wyj艣ciowych) - je艣li si臋 zatrzymuje dla danych spe艂niaj膮cych warunek pocz膮tkowy, to wyniki spe艂niaj膮 warunek ko艅cowy.
Algorytm poprawny - (dla dowolnych danych wej艣ciowych i dowolnych danych wyj艣ciowych) - zawsze si臋 zatrzymuje dla danych spe艂niaj膮cych warunek pocz膮tkowy i wyniki spe艂niaj膮 warunek ko艅cowy.
Z艂o偶ono艣膰 obliczeniowa algorytmu to z艂o偶ono艣膰 czasowa i pami臋ciowa.
Operacja elementarna (inaczej operacja dominuj膮ca) to operacja charakterystyczna dla danego algorytmu. To taka operacja, 偶e 艂膮czna ich liczba jest proporcjonalna do liczby wykona艅 wszystkich operacji jednostkowych w dowolnej komputerowej realizacji algorytmu.
Za jednostk臋 z艂o偶ono艣ci czasowej przyjmuje si臋 wykonanie jednej operacji elementarnej (dominuj膮cej). Z艂o偶ono艣膰 czasowa algorytmu jest funkcj膮 rozmiaru danych.
M贸wimy, 偶e f jest co najwy偶ej rz臋du g, co zapisujemy f(n)=O(g(n))
M贸wimy, 偶e f jest co najmniej rz臋du g, co zapisujemy f(n)=惟(g(n))
M贸wimy, 偶e f jest dok艂adnie rz臋du g, co zapisujemy f(n)=螛(g(n))
! Aby zastosowa膰 strategi臋 dziel i zwyci臋偶aj nale偶y mie膰 ci膮g posortowany niemalej膮co.
Wyszukiwanie elementu w wektorze:
Przy zastosowaniu standardu koszt jest liniowy, a dane „najgorszego” przypadku to ci膮g, w kt贸rym x (szukany element) nie wyst臋puje i wszystkie liczby w ci膮gu s膮 mniejsze od x.
Przy zastosowaniu dziel i zwyci臋偶aj mamy koszt
a przypadek pesymistyczny to nie wyst膮pienie x.
Wyszukiwanie min i max:
Standard: Koszt jest liniowy 2(n-1), a przypadkiem pesymistycznym jest ustawienie element贸w malej膮co.
Dziel i zwyci臋偶aj: Koszt jest liniowy
, a przypadek pesymistyczny spe艂niaj膮 dowolne dane spe艂niaj膮ce warunek pocz膮tkowy.
Sprawdzanie czy punkt nale偶y do wielok膮ta wypuk艂ego:
Naiwny: Koszt jest n^3 (mo偶na go obni偶y膰 do n je艣li b臋dzie dobiera艂o si臋 tr贸jk膮ty o wsp贸lnym wierzcho艂ku n-1).
Dziel i zwyci臋偶aj: Koszt
Rekord wywo艂ania (aktywacji) zawiera:
-warto艣ci wszystkich parametr贸w funkcji,
-zmienne lokalne funkcji
-adres powrotu - adres instrukcji w kodzie programu, nast臋puj膮cej bezpo艣rednio po
wywo艂aniu funkcji
-dynamiczne dowi膮zanie - wska藕nik na poprzedni rekord aktywacji
-zwracana warto艣膰 funkcji
Rodzaje rekurencji:
1.Rekursja ko艅cowa
Zawiera tylko jedno wywo艂anie rekurencyjne na ko艅cu funkcji. Taki rodzaj rekursji jest po prostu innym zapisem p臋tli i mo偶e by膰 艂atwo zast膮piony p臋tl膮.
2.Rekursja nieko艅cowa
Zawiera jedno wywo艂anie rekurencyjne, kt贸re nie jest ostatnim rozkazem funkcji. Iteracyjna wersja takiej funkcji wymaga zazwyczaj jawnego u偶ycia stosu.
3.Rekursja po艣rednia
Przyk艂ad: funkcja f wywo艂uje funkcj臋 g, a g wywo艂uje funkcj臋 f
4.Rekursja zagnie偶d偶ona
Kiedy funkcja jest zdefiniowana nie tylko za pomoc膮 samej siebie, ale tak偶e jest u偶yta jako jeden z parametr贸w. Przyk艂adem jest funkcja Ackermana (funkcja Ackermanna ro艣nie bardzo, bardzo szybko i nie daje si臋 zapisa膰 wzorem, w kt贸rym mo偶na u偶y膰 operacji arytmetycznych, takich jak dodawanie, mno偶enie i pot臋gowanie).
Programowanie dynamiczne
U偶ycie strategii programowania dynamicznego polega na zapami臋taniu w odpowiedniej strukturze (najcz臋艣ciej tablicy) wynik贸w rozwi膮zania podproblem贸w, na kt贸re zosta艂 podzielony problem zasadniczy, unikaj膮c w ten spos贸b wielokrotnych oblicze艅 dla tego samego podproblemu. Programowanie dynamiczne prowadzi do ca艂kowitej b膮d藕 cz臋艣ciowej eliminacji rekurencji.
Obliczanie dwumianu Newtona przy pomocy tr贸jk膮ta Pascala: koszt O(2n-m).
Stosuj膮c programowanie dynamiczne uzyskujemy koszt
Optymalne mno偶enie macierzy:
Naiwny: Sprawdzamy wszystkie mo偶liwo艣ci; koszt:
Dynamicznie: Pesymistycznie koszt wynosi
.
Dla problemu triangulacji wielok膮ta mo偶na wykorzysta膰 powy偶szy algorytm (koszty identyczne).
Sortowanie przez scalanie:
Sk艂ada si臋 z dw贸ch procedur: procedura Merge, gdy ka偶dy z ci膮g贸w scalanych ma d艂ugo艣膰 k i wynosi 2k-1 za艣 Merge_Sort
, czyli og贸lnie jest log.
Sortowanie przez kopcowanie
Aby mog艂o zaj艣膰 musz膮 by膰 spe艂nione 2 warunki:
&
Fazy sortowania przez kopcowanie:
I Faza: budowa kopca (procedura down_heap i construct)
II Faza: zamiana elementu pierwszego z ostatnim (procedura delete_max)
III Faza: przywracanie struktury kopca (znowu down_heap w delete_max)
l-poziom
Procedura downheap wywo艂ana dla w臋z艂a i z poziomu l wykonuje co najwy偶ej
por贸wna艅. Koszt construct jest liniowy (n). Delete_max ma koszt
. Og贸lnie ca艂a procedura Heap_Sort ma kosz
. Nie jest znana pe艂na analiza 艣redniej z艂o偶ono艣ci czasowej sortowania przez kopcowanie.Wyniki przeprowadzonych eksperyment贸w wskazuj膮, 偶e wsp贸艂czynnik przy nlogn jest bliski 2.
Sortowanie szybkie (QuickSort)
Czas dzia艂ania algorytmu Quick_Sort zale偶y od tego, czy podzia艂y s膮 zr贸wnowa偶one, czy nie. Je偶eli podzia艂y s膮 zr贸wnowa偶one, to algorytm jest asymptotycznie tak szybki jak sortowanie przez scalanie. Kiedy podzia艂y s膮
niezr贸wnowa偶one, to algorytm mo偶e dzia艂a膰 asymptotycznie tak wolno jak sortowanie przez wstawianie.
Najgorszy przypadek podzia艂贸w:
Zachodzi wtedy, gdy funkcja Partition zwraca taki indeks podzia艂u, 偶e jeden z obszar贸w ma n-1 element贸w, a drugi zawiera tylko 1 element. Je偶eli taka sytuacja zachodzi w ka偶dym kroku algorytmu, to liczba wykonywanych por贸wna艅 jest najwi臋ksza.
Je偶eli elementem dziel膮cym jest pierwszy element sortowanego ci膮gu, to najgorszy przypadek podzia艂贸w zachodzi dla ci膮gu uporz膮dkowanego. (Koszt n^2).
Najlepszy przypadek podzia艂贸w:
Ma miejsce wtedy, gdy funkcja dziel膮ca Partition „produkuje” dwa obszary o rozmiarach n/2. (Koszt
).
Stos wykorzystywany jest w algorytmie przegl膮dania grafu „w g艂膮b”, kolejka „wszerz” oraz sito Eratostenesa. List臋 mo偶na posortowa膰 kosztem O(nlogn).
Drzewo BST
Drzewo BST (Binary Search Tree) jest drzewem binarnym z ustalonym porz膮dkiem symetrycznym. Porz膮dek symetryczny polega na tym, 偶e dla ka偶dego w臋z艂a x drzewa jest spe艂niony nast臋puj膮cy warunek:
Je偶eli y le偶y w lewym poddrzewie x, to key(y) 鈮 key(x).
Je偶eli y le偶y w prawym poddrzewie x, to key(x) 鈮 key(y).
Relacja 鈮 jest relacj膮 porz膮dku liniowego, a key(x) - jest warto艣ci膮 pola (klucza) danych, na kt贸rym relacja 鈮 jest okre艣lona.
Search, Insert maj膮 koszty liniowe. Ka偶dy element dodany do BST jest li艣ciem.
Wysoko艣膰 drzewa AVL o n wierzcho艂kach (n鈮1) jest nie wi臋ksza ni偶 2log2n.
Operacje s艂ownikowe na drzewie AVL
search(e, d) - operacja realizowana tak samo jak dla drzewa BST
insert(e, d) - operacja realizowana w pierwszej fazie tak samo jak dla drzewa BST, tj. nowy element jest wstawiany jako li艣膰 w odpowiednim miejscu w drzewie. Druga faza to
ewentualne wywa偶enie powsta艂ego drzewa.
delete(e, d) - operacja realizowana w pierwszej fazie tak samo jak dla drzewa BST, tj. w miejsce usuwanego elementu wstawiany jest najwi臋kszy element w lewym poddrzewie usuwanego elementu albo najmniejszy element w jego prawym poddrzewie. Druga faza to ewentualne wywa偶enie powsta艂ego drzewa.
Rotacje w procesie wywa偶ania wykonywane s膮 tylko na jednej 艣cie偶ce w drzewie.
Operacja delete realizowana na drzewie AVL wymaga wykonania co najwy偶ej 2log2n rotacji.
Operacja insert realizowana na drzewie AVL wymaga wykonania co najwy偶ej jednej rotacji.
Operacje s艂ownikowe zrealizowane na drzewie AVL maj膮 koszt pesymistyczny O(logn).
Analiza koszt贸w haszowania metod膮 艂a艅cuchow膮
Niech 伪 oznacza wsp贸艂czynnik zape艂nienia tablicy haszuj膮cej:
, gdzie n to aktualna liczba danych w s艂owniku, a m to rozmiar tablicy haszuj膮cej. Warto艣膰 wsp贸艂czynnika 伪 to 艣rednia d艂ugo艣膰 listy (艂a艅cucha).
W przypadku pesymistycznym wszystkie operacje s艂ownikowe maj膮 z艂o偶ono艣膰 螛(n), zak艂adaj膮c, 偶e koszt obliczania warto艣ci funkcji haszuj膮cej dla danego elementu jest 螛(1).
Przy okre艣laniu z艂o偶ono艣ci 艣redniej przyjmuje si臋, 偶e losowo wybrany element z jednakowym prawdopodobie艅stwem trafia na ka偶d膮 z m pozycji, niezale偶nie od tego gdzie trafiaj膮 inne elementy. Je偶eli spe艂nione jest to za艂o偶enie, to m贸wimy o prostym r贸wnomiernym haszowaniu.
Mo偶na pokaza膰, 偶e:
Twierdzenie
W tablicy z haszowaniem wykorzystuj膮cym 艂a艅cuchow膮 metod臋 rozwi膮zywania problemu kolizji, przy za艂o偶eniu, o prostym r贸wnomiernym haszowaniu, 艣redni czas dzia艂ania operacji search wynosi 螛(1+伪).
Wniosek:
艢redni czas realizacji operacji insert i delete wynosi 螛(1+伪).
Adresowanie otwarte
Wszystkie elementy s艂ownika s膮 przechowywane wprost w tablicy. Wyszukiwanie elementu polega na systematycznym sprawdzaniu pozycji w tablicy, a偶 zostanie znaleziony szukany element albo wiadomo ju偶, 偶e na pewno nie ma go w tablicy. Nie ma 偶adnych dodatkowych list. Przy stosowaniu haszowania otwartego wsp贸艂czynnik zape艂nienia 伪 nie mo偶e wi臋kszy od 1, aby nie nast膮pi艂o przepe艂nienie tablicy.
Operacja delete realizowana metod膮 haszowania otwartego jest do艣膰 skomplikowana i kosztowna czasowo (koszt nie zale偶y od wsp贸艂czynnika zape艂nienia tablicy).
Adresowanie liniowe
Powa偶n膮 wad膮 adresowania liniowego jest tendencja do grupowania si臋 zaj臋tych pozycji. d艂ugie sp贸jnie wype艂nione ci膮gi zaj臋tych pozycji szybko si臋 powi臋kszaj膮, co znacznie spowalnia operacj臋 wyszukiwania.
Adresowanie kwadratowe
Stosujemy tu funkcj臋 postaci:
gdzie
jest zwyk艂膮 jednoargumentow膮 funkcj膮 haszuj膮c膮,
i
s膮 sta艂ymi, a
.
Dla danej e jej ci膮g kontrolny zaczyna si臋 od pozycji
. Nast臋pna pozycja w tym ci膮gu jest oddalona od pierwszej o wielko艣膰 zale偶n膮 od kwadratu numeru pozycji i w ci膮gu kontrolnym. Dob贸r sta艂ych
i
w decyduj膮cy spos贸b mo偶e wp艂yn膮膰 na efektywno艣膰 operacji insert i search realizowanych metod膮 adresowania kwadratowego.
Zauwa偶my, 偶e je偶eli dwa elementy maj膮 w takie same pocz膮tkowe pozycje, to i ca艂e ich ci膮gi kontrolne s膮 r贸wne, poniewa偶 z
wynika, 偶e
. Prowadzi to do tzw. grupowania wt贸rnego. Pocz膮tkowa pozycja okre艣la jednoznacznie, podobnie jak w adresowaniu liniowym, ca艂y ci膮g kontrolny.
Haszowanie dwukrotne
Haszowanie dwukrotne dopuszcza u偶ycie 螛(m2) r贸偶nych ci膮g贸w kontrolnych, a nie tylko 螛(m) ci膮g贸w jak w haszowaniu liniowym i kwadratowym. Ka偶da para
wyznacza inny ci膮g kontrolny, a dla r贸偶nych element贸w warto艣ci
i
zmieniaj膮 si臋 niezale偶nie. Dzi臋ki temu haszowanie dwukrotne bardzo dobrze przybli偶a "idealne" warunki haszowania r贸wnomiernego.
Koszt operacji insert i search w adresowaniu otwartym
Je偶eli wsp贸艂czynnik zape艂nienia tablicy z haszowaniem
, to 艣rednia liczba por贸wna艅 wykonanych w czasie realizacji operacji search i insert metod膮 adresowania otwartego jest nie wi臋ksza ni偶
, o ile jest spe艂nione za艂o偶enie o r贸wnomiernym haszowaniu.
Przegl膮danie grafu „wszerz”
Jako operacj臋 elementarn膮 przyjmujemy wykonanie operacji in lub out na kolejce Q oraz operacj臋 przegl膮dania list incydencji grafu. Ka偶dy wierzcho艂ek jest wstawiany co najwy偶ej raz i co najwy偶ej raz jest z niej usuwany. St膮d 艂膮czny czas wykonania operacji na kolejce wynosi O(n). Poniewa偶 lista incydencji ka偶dego wierzcho艂ka jest przegl膮dana tylko wtedy, gdy wierzcho艂ek zostanie usuni臋ty z kolejki, lista incydencji ka偶dego wierzcho艂ka jest przegl膮dana co najwy偶ej raz. Suma d艂ugo艣ci wszystkich list wynosi 螛(m). 艁膮czny czas przegl膮dania list wynosi zatem O(m). Inicjowanie grafu zabiera czas O(n).Koszt BFS wynosi O(m+n).
Przegl膮danie grafu w „g艂膮b”
Jako operacj臋 elementarn膮 przyjmujemy liczb臋 wywo艂a艅 rekurencyjnych procedury DFS_VISIT (operacje stosowe realizowane w stosie wywo艂a艅) oraz operacj臋 przegl膮dania list incydencji grafu. Koszt procedury DFS wynosi O(m+n) - uzasadnienie analogiczne jak dla BFS.
Algorytmy zach艂anne
Dwie cechy charakterystyczne:
W艂asno艣膰 wyboru zach艂annego
Je偶eli wybory "lokalne" s膮 optymalne, to wyb贸r "globalny" (ostateczny)
jest optymalny. R贸偶nica mi臋dzy strategi膮 zach艂ann膮 a programowaniem dynamicznym polega na tym, 偶e w programowaniu dynamicznym w ka偶dym kroku podejmowane s膮 decyzje, kt贸rych wyb贸r zale偶y od rozwi膮za艅 podproblem贸w. W algorytmie zach艂annym wybory s膮 podejmowane jako najlepsze (z punktu widzenia zadania) w danej chwili. Wybory podejmowane w algorytmie zach艂annym nie s膮 zale偶ne od wybor贸w przesz艂ych, w przeciwie艅stwie do wybor贸w podejmowanych przy strategii programowania dynamicznego. Mo偶na formalnie udowodni膰 (stosuj膮c metod臋 indukcji), 偶e dany problem ma w艂asno艣膰 wyboru zach艂annego.
W艂asno艣膰 optymalnej podstruktury
Problem ma w艂asno艣膰 optymalnej podstruktury, je偶eli optymalne rozwi膮zanie jest funkcj膮 optymalnych rozwi膮za艅 podproblem贸w. Ta w艂asno艣膰 jest r贸wnie偶 spe艂niona dla problem贸w rozwi膮zywalnych metod膮 programowania dynamicznego.
Dyskretny problem plecakowy nie ma w艂asno艣ci wyboru zach艂annego. Dyskretny problem plecakowy ma w艂asno艣膰 optymalnej podstruktury. Ci膮g艂y problem plecakowy ma w艂asno艣ci wyboru zach艂annego. Ci膮g艂y problem plecakowy ma w艂asno艣膰 optymalnej podstruktury.
Koszt z艂odzieja z plecakiem (ci膮g艂y) wynosi: 螛(nlogn). Kruskal i Huffman te偶 wykorzystuj膮 algorytm zach艂anny. Problem planu zaj臋膰 wykona si臋 kosztem liniowym o ile dane sa uporz膮dkowane rosn膮co wzgl臋dem czas贸w zako艅czenia zaj臋膰.
Z艂o偶ono艣膰 czasowa algorytmu Kruskala
Rozmiar zadania: n - liczba wierzcho艂k贸w grafu,
m - liczba kraw臋dzi grafu
Koszt operacji MAKE_SETS: O(n)
Koszt utworzenia posortowanej listy kraw臋dzi L: O(nlogn)
Koszt operacji FIND_SET zrealizowanych w p臋tli (*): O(m)
Koszt operacji UNION zrealizowanych w p臋tli (*): O(nlogn)
Uwaga ! Koszt pojedynczej operacji UNION, w przypadku pesymistycznym jest O(n), ale koszt n-1 operacji UNION w p臋tli (*) jest O(nlogn), a nie O(n2). Liczymy bowiem, ile razy dany element mo偶e mie膰 zmieniane dowi膮zanie do g艂owy listy. Za ka偶dym razem element przechodzi do listy o rozmiarze co najmniej dwukrotnie wi臋kszym. Zmian takich mo偶e by膰 co najwy偶ej logn.
Wniosek
Z艂o偶ono艣膰 czasowa algorytmu Kruskala zrealizowanego w strukturze
listowej jest O(m + nlogn)
Algorytm Huffmana
d艂ugo艣膰 ci膮gu wej艣ciowego - d艂ugo艣膰 ci膮gu wyj艣ciowego
d艂ugo艣膰 ci膮gu wej艣ciowego
To jest najlepszy wsp贸艂czynnik kompresji - mniejszego ju偶 nie mo偶na uzyska膰.
Aby kompresja by艂a poprawna musz膮 by膰 spe艂nione nast臋puj膮ce warunki:
-Ka偶dy kod odpowiada dok艂adnie jednemu symbolowi.
-Dekodowanie nie powinno wymaga膰 podgl膮dania wi臋kszego fragmentu zakodowanego tekstu. Po wczytaniu z pliku pojedynczego symbolu powinni艣my umie膰 stwierdzi膰, czy osi膮gni臋ty zosta艂 koniec napisu koduj膮cego symbol pierwotnej wiadomo艣ci. Nie s膮 wi臋c potrzebne 偶adne specjalne znaki oddzielaj膮ce dwa kody w s膮siedniej wiadomo艣ci.
Koszt czasowy algorytmu kompresji:
Rozmiar zadania: n - rozmiar alfabetu
m - liczba znak贸w pliku, kt贸ry kompresujemy
Tworzenie uporz膮dkowanej listy jednow臋z艂owych drzew
kosztuje optymalnie 螛(nlogn).
Jeden krok procesu scalania dw贸ch w臋z艂贸w drzewa Huffmana jest realizowany kosztem sta艂ym 螛(1). Ca艂y proces tworzenia drzewa Huffmana kosztuje zatem 螛(n).
Proces ustalania wszystkich kod贸w kompresji kosztuje 螛(n).
Mo偶na go zrealizowa膰 stosuj膮c metod臋 przegl膮dania drzewa
binarnego w porz膮dku inorder (poprzeczny: L - K- P).
Krok algorytmu kompresji, kt贸ry ustala kody znak贸w wpisywanych do skompresowanego pliku ma r贸wnie偶 koszt rz臋du 螛(m).
St膮d wynika, 偶e koszt algorytmu kompresji metod膮 Huffmana pliku zawieraj膮cego m znak贸w nad n elementowym alfabetem wynosi 螛(nlogn+m).
Sortowanie przez zliczanie
Koszt inicjalizacji tablicy C: k
Koszt I kroku: n
Koszt II kroku: k-1
Koszt III kroku: 2n
Koszt 艂膮czny: 2k + 3n - 1=O(n+k)
Sortowanie pozycyjne
Z艂o偶ono艣膰 czasowa : Zale偶y od metody sortowania jak膮 zastosuje my w pojedynczym kroku tj. po danej cyfrze. Musi by膰 to metoda stabilna. Je偶eli ka偶da z cyfr nale偶y do przedzia艂y od 1 do k oraz k nie jest zbyt du偶e, to nale偶y u偶y膰 sortowania przez zliczanie. Ka偶dy przebieg przez n cyfr d- cyfrowych liczb wymaga czasu 螛(n+k). Poniewa偶 algorytm wykonuje d przebieg贸w, wi臋c ca艂kowity czas dzia艂ania sortowania pozycyjnego wynosi 螛(dn+dk). Je艣li d jest sta艂膮, a k=O(n), to sortowanie pozycyjne dzia艂a w czasie liniowym.
Sortowanie kube艂kowe
Z艂o偶ono艣膰 czasowa:
Koszt pierwszej p臋tli wynosi O(n).
Koszt operacji 艂膮czenia list B[i] jest r贸wnie偶 O(n).
Koszt drugiej p臋tli zale偶y od d艂ugo艣ci list B[i].
Niech ni oznacza liczb臋 element贸w w kube艂ku B[i].
Sortowanie przez wstawianie ma koszt pesymistyczny O(n2) dla ci膮gu
d艂ugo艣ci n.
Mo偶na pokaza膰, 偶e koszt 艣redni drugiej p臋tli wynosi O(n).
Sortowanie kube艂kowe ma pesymistyczny koszt O(n2 ), a 艣redni O(n).
Wyszukiwanie wzorca w tek艣cie
Koszt czasowy algorytmu naiwnego
Operacj膮 elementarn膮 s膮 por贸wnania mi臋dzy znakami wzorca
i tekstu. Je艣li wzorzec nie wyst臋puje w tek艣cie i przekonujemy si臋 o tym po pierwszym por贸wnaniu (przy ka偶dym po艂o偶eniu wzorca wzgl臋dem tekstu), to wykonujemy minimaln膮 liczb臋 por贸wna艅 r贸wn膮 n-m+1. Je偶eli wzorzec wyst臋puje na ka偶dej pozycji tekstu, na przyk艂ad, gdy:
T: an, P: am,
to wykonujemy maksymaln膮 liczb臋 por贸wna艅 r贸wn膮 :
(n - m+1)鈰 m.
Zatem:
Mo偶na pokaza膰, 偶e koszt 艣redni algorytmu naiwnego jest O(n-m+1).
Koszt czasowy algorytmu KMP
Koszt obliczenia wszystkich warto艣ci funkcji 飦 wynosi O(m), gdy偶 :
(1) warunek P[k+1] =P[q] (po p臋tli) mo偶e by膰 sprawdzany co
najwy偶ej m razy, a z drugiej strony,
(2) warunek P[k+1]<>P[q] (w p臋li) te偶 mo偶e by膰 sprawdzany
co najwy偶ej m razy.
St膮d, razem mamy co najwy偶ej 2m por贸wna艅.
Mo偶na uzasadni膰, 偶e koszt 艣redni zasadniczego algorytmu KMP jest O(n).
Mo偶na pokaza膰, 偶e ca艂kowity koszt 艣redni algorytmu KMP wynosi O(n+m).
Koszt czasowy algorytmu RK
Operacj膮 elementarn膮 nie s膮 tym razem por贸wnania mi臋dzy znakami wzorca i tekstu, a operacje arytmetyczne realizowane przy obliczaniu odcisku wzorca i tekstu.
Odcisk wzorca mo偶na policzy膰 kosztem O(m). Odcisk t0 r贸wnie偶 mo偶na obliczy膰 takim samym kosztem. Odciski t1,...,tn-m mo偶na policzy膰 sta艂ym kosztem, gdy mamy wcze艣niej policzon膮 jednorazowo warto艣膰 10 m-1 (mo偶na t臋 warto艣膰 policzy膰 kosztem O(logm), stosuj膮c algorytm oparty na metodzie "dziel i zwyci臋偶aj". Zatem koszt ca艂ego algorytmu wyniesie O(n+m).
Problem 1
Warto艣ci p i t0, t1,..., tn-m mog膮 by膰 bardzo du偶e, a wtedy trudno uwa偶a膰 偶e ka偶da operacja arytmetyczna ma ten sam koszt.
Rozwi膮zanie Problemu 1
Problem ten mo偶na rozwi膮za膰 stosuj膮c zamiast zwyk艂ej arytmetyki, arytmetyk臋 modulo.
Obliczone warto艣膰 odcisku dzieli si臋 modulo pewna wybrana
liczba pierwsza q.
Zwykle wybiera si臋 q takie, 偶e d鈰q ( w naszych przyk艂adach d = 10) powinno by膰 nie wi臋ksze ni偶 jedno s艂owo maszynowe.
Obliczanie nast臋pnego ''odcisku palca'' dla tekstu wygl膮da nast臋puj膮co:
ts+1 =(d鈰(ts - d m-1鈰T[s+1])+T[s+m+1]) mod q
Problem 2
Pojawia si臋 jednak problem jednoznaczno艣ci:
Prawdziwo艣膰 warunku t s = p mod q nie oznacza, 偶e na pewno
P[1...m]=T[s+1 ... s+m]
Aby algorytm nie zwraca艂 niepoprawnych wynik贸w nale偶y w ka偶dym przypadku gdy ts = p mod q dodatkowo sprawdzi膰 r贸wno艣膰 odpowiednich ci膮g贸w badaj膮c je znak po znaku.
Powoduje to jednak, 偶e koszt algorytmu RK, w najgorszym przypadku wynosi 螛((n-m+1) 鈰m).
Przyk艂adem przypadku pesymistycznego dla algorytmu RK jest przypadek: T = an i P = am. W贸wczas ka偶dy blok tekstu o d艂ugo艣ci m daje ten sam odcisk r贸wny odciskowi wzorca i konieczne jest sprawdzenie znak po znaku.
W bardzo wielu zastosowaniach , zaj艣cie zdarzenia
ts = p mod q,
przy jednoczesnej niezgodno艣ci wzorca z tekstem, jest bardzo rzadkie. Liczb臋 q mo偶na tak wybra膰 aby prawdopodobie艅stwo, 偶e ts = p mod q by艂o r贸wne 1/n. Wtedy czas oczekiwany wykonania algorytmu RK wynosi O(n+m).
Wersja bez sprawdzania symbol po symbolu i z arytmetyk膮 modulo q gwarantuje za艣 liniowy czas wykonania, ale z ma艂ym prawdopodobie艅stwem wynik mo偶e si臋 okaza膰 niepoprawny. Takie algorytmy, kt贸re z dopuszczalnym prawdopodobie艅stwem zwracaj膮 wynik niepoprawny nazywamy algorytmami MonteCarlo (zawsze szybko i prawdopodobnie poprawnie). Wersja algorytmu ze sprawdzaniem w przypadku, gdy odcisk wzorca jest zgodny mod q z odciskiem bloku tekstu gwarantuje poprawny wynik, ale z ma艂ym prawdopodobie艅stwem algorytm ten b臋dzie dzia艂a艂 d艂u偶ej ni偶 liniowo (metoda LasVegas - zawsze poprawnie i prawdopodobnie szybko).
Geometria obliczeniowa
Koszt sprawdzania czy punkt nale偶y do dowolnego wielok膮ta jest liniowy.
Koszt czasowy algorytmu naiwnego
Rozmiar zadania:
- liczba punkt贸w zbioru S.
Operacja elementarna:
operacja sprawdzania, czy punkt nale偶y do tr贸jk膮ta
(odcinka) w Kroku 1,
operacja por贸wnania wykonana w trakcie sortowania
w Kroku 2.
Koszt czasowy Kroku 1: Dla n punkt贸w trzeba sprawdzi膰 co najwy偶ej
r贸偶nych tr贸jk膮t贸w. St膮d koszt Kroku 1 jest O(n4).
Koszt czasowy Kroku 2: Je偶eli zastosujemy optymaln膮 metod臋 sortowania to koszt czasowy Kroku 2 jest O(nlogn).Ca艂kowity koszt czasowy algorytmu naiwnego jest wi臋c rz臋du
O(n4). Efektywne algorytmy rozwi膮zuj膮ce problem otoczki wypuk艂ej, algorytm Grahama i Jarvisa, maj膮 zasadniczo ni偶szy koszt.
Koszt czasowy algorytmu Grahama
Na z艂o偶ono艣膰 algorytmu Grahama decyduj膮cy wp艂yw ma Krok 2. Kroki 1 i 2 wykonywane s膮 w czasie liniowym.
Krok 2 mo偶na zrealizowany w czasie O(nlogn), stosuj膮c efektywn膮 metod臋 sortowania (np. sortowanie przez scalanie,
sortowanie przez po艂贸wkowe wstawianie czy sortowanie szybkie).
艁atwo zauwa偶y膰, 偶e zamiast sprawdza膰, czy punkt next(q) le偶y wewn膮trz tr贸jk膮ta O q next(next(q)) mo偶na testowa膰, czy next(q) le偶y po lewej stronie (lub nale偶y do) wektora
. Z艂o偶ono艣膰 algorytmu Grahama nie zale偶y od liczby punkt贸w otoczki wypuk艂ej. Nast臋pny algorytm rozwi膮zuj膮cy problem otoczki, algorytm Jarvisa, ma z艂o偶ono艣膰 O(kn), gdzie k jest liczb膮 punkt贸w otoczki wypuk艂ej w danym n elementowym zbiorze punkt贸w.
Z艂o偶ono艣膰 czasowa algorytmu Jarvisa
Ka偶da iteracja w Krokach 2 i 3 jest wykonywana w czasie O(n). Poniewa偶 liczba iteracji jest r贸wna liczbie wierzcho艂k贸w otoczki, to koszt ca艂kowity algorytmu Jarvisa wynosi O(kn).
Algorytm ten jest szczeg贸lnie przydatny wtedy, gdy wiemy, 偶e liczba punkt贸w otoczki wypuk艂ej jest niewielka w por贸wnaniu z rozmiarem zbioru S (na przyk艂ad ograniczona przez sta艂膮 niezale偶n膮 od n).
Algorytm znajdowania najmniej odleg艂ych punkt贸w
Koszt czasowy algorytmu naiwnego
Liczba par punkt贸w do sprawdzenia wynosi
. St膮d koszt
algorytmu jest
Koszt czasowy algorytmu znajdywania najmniej odleg艂ej pary punkt贸w
Koszt sortowania wst臋pnego (przed pierwszym wywo艂aniem rekurencyjnym) tablic X i Y wynosi 螛(nlogn). Dzi臋ki temu, 偶e tablica X jest posortowana, krok polegaj膮cy na rozdzieleniu zbioru punkt贸w P na podzbiory PL i PR mo偶na 艂atwo zrealizowa膰 w czasie liniowym. Dzi臋ki temu, 偶e tablica Y jest posortowana, sta艂膮 liczb膮 por贸wna艅 mo偶na zrealizowa膰 krok
polegaj膮cy na sprawdzeniu, czy istniej膮 dwa punkty, le偶膮ce po przeciwnych stronach prostej l, kt贸rych odleg艂o艣膰 jest mniejsza od
.
Posortowane tablice zostaj膮 przekazane jako parametry pierwszego wywo艂ania rekurencyjnego, a potem rozdziela si臋 je (pod warunkiem, 偶e zawieraj膮 co najmniej trzy punkty) na dwie, r贸wnie偶 posortowane tablice: z tablicy X otrzymujemy tablice XL i XR , a tablicy Y otrzymujemy tablice YL i YR . Wszystkie cztery tablice r贸wnie偶 musz膮 by膰 posortowane. Aby unikn膮膰 ponownego sortowania ca艂ych tablic, podczas rozdzielania tablic X i Y stosujemy technik臋 podobn膮, ale odwrotn膮 do procedury MERGE (scalania) w algorytmie sortowania MergeSort.
Algorytm zamiatania
Algorytm naiwny
Sprawdzamy wszystkie mo偶liwe pary odcink贸w. Koszt algorytmu naiwnego jest r贸wny
Koszt czasowy algorytmu sprawdzania przecinania si臋 odcink贸w
Je艣li S zawiera n odcink贸w, to algorytm dzia艂a w czasie O(nlogn). Czas tworzenia posortowanej listy L mo偶e optymalnie wynie艣膰 O(nlogn). P臋tla wykonuje co najwy偶ej 2n krok贸w, bo tyle co najwy偶ej zdarze艅 mo偶e zaj艣膰 dla n odcink贸w. Ka偶dy krok p臋tli realizuje si臋 w czasie O(logn), pod warunkiem, 偶e struktura stanu miot艂y jest realizowana optymalnie.
Problemy 艂atwo rozwi膮zalne to takie, dla kt贸rych mo偶na poda膰 algorytm o wielomianowej z艂o偶ono艣ci czasowej, czyli taki, kt贸rego koszt jest O(nk) (dla pewnego k).
Problemy o z艂o偶ono艣ci wy偶szej ni偶 wielomianowa, czyli takiej, 偶e nie da si臋 jej ograniczy膰 przez O(nk), dla dowolnego k, nazywamy trudno rozwi膮zalnymi.
Z艂o偶ono艣膰 algorytmu rozwi膮zuj膮cego problem wie偶 Hanoi
Mo偶na wykaza膰, 偶e nie istnieje algorytm rozwi膮zuj膮cy problem wie偶 Hanoi o z艂o偶ono艣ci ni偶szej ni偶 螛(2n).
Algorytm znalezienia cyklu Hamiltona
Koszt algorytmu naiwnego to
Z艂o偶ono艣膰 czasowa algorytmu generowania cykli Hamiltona (strategia powrot贸w)
Drzewo mo偶liwych "rozszerze艅" rozwi膮zania cz臋艣ciowego jest drzewem wielokierunkowym o wysoko艣ci r贸wnej co najwy偶ej n. Je偶eli za operacj臋 elementarn膮 przyjmiemy ka偶de wywo艂anie rekurencyjne procedury Hamilton, to koszt algorytmu jest r贸wny liczbie w臋z艂贸w w drzewie. Mo偶na pokaza膰, 偶e liczba ta jest O(2n).
Problem ustawienia Hetman贸w
Przyk艂ady problem贸w klasy NP.
-Generowanie cyklu Hamiltona w sp贸jnym grafie
-Problemy u艂o偶e艅 dwuwymiarowych (czy z wielok膮t贸w da si臋 u艂o偶y膰 prostok膮t)
-Problem komiwoja偶era
-Problem u艂o偶enia planu
-Ustalanie prawdy logicznej (problem spe艂nialno艣ci)
-Kolorowanie map i graf贸w
-Problem kliki
-Sprawiedliwy podzia艂
-Szeregowanie zada艅 niezale偶nych
-Izomorfizm z podgrafem
Przyk艂ady problem贸w klasy NP.-zupe艂nych
Wszystkie wy偶ej wymienione si臋 do nich zaliczaj膮.
M贸wimy, 偶e problem decyzyjny A jest przekszta艂calny w problem decyzyjny B, je艣li istnieje przekszta艂cenie f :A鈫B o nast臋puj膮cych w艂asno艣ciach:
odpowiedzi do problem贸w A i B s膮 zgodne, warto艣膰 f(A) mo偶na obliczy膰 w czasie wielomianowo zale偶nym od rozmiaru zadania A.
Je偶eli problem A jest przekszta艂calny w problem B oraz A jest problemem klasy NP, to tak偶e problem B jest problemem klasy NP.
Je偶eli problem A jest NP - zupe艂ny i jest przekszta艂calny w problem B oraz B jest problem klasy NP, to B jest NP - zupe艂ny.
Hipoteza P鈮NP.
Nast臋puj膮ce warunki s膮 r贸wnowa偶ne:
Istnieje problem NP- zupe艂ny, kt贸ry jest trudno rozwi膮zalny.
Ka偶dy problem NP - zupe艂ny jest trudno rozwi膮zalny.
Je偶eli ta hipoteza jest prawdziwa, to nie warto szuka膰 rozs膮dnych rozwi膮za艅 dla problem贸w NP - zupe艂nych, bo ich po prostu nie ma.
Hipoteza P=NP.
Nast臋puj膮ce warunki s膮 r贸wnowa偶ne:
Istnieje problem NP- zupe艂ny, kt贸ry jest 艂atwo rozwi膮zalny (nale偶y do klasy P).
Ka偶dy problem NP - zupe艂ny mo偶e by膰 rozwi膮zany w czasie wielomianowym.
Je偶eli ta hipoteza jest prawdziwa, to je偶eli uda si臋 poda膰 rozwi膮zanie wielomianowe jednego problemu NP- zupe艂nego, to tym samym rozwi膮zalne wielomianowo b臋d膮 pozosta艂e problemy z tej klasy.
Algorytm umo偶liwiaj膮cy otrzymanie prawie optymalnego rozwi膮zania jest nazywany algorytmem aproksymacyjnym (przybli偶onym).
Z艂o偶ono艣膰 czasowa algorytmu przybli偶onego (komiwoja偶er)
Przy jednym uruchomieniu : O(n2).
Przy n uruchomieniach: O(n3)