NJ/A+SD/1 Algorytmy i struktury danych Norbert Jankowski norbert@is.umk.pl www.is.umk.pl/ norbert/asd Uwagi mile widziane!
Literatura [1] A. V. Aho, J. E. Hopcroft, J. D. Ullman. Projektowanie i analiza algorytmów. Helion, Warszawa, 2003. [2] A. V. Aho, J. E. Hopcroft, J. D. Ullman. Projektowanie i analiza algorytmów. Państwowe Wydawnictwa Naukowe, Warszawa, 1983. [3] Niklaus Wirth. Algorytmy + Struktury Danych = Programy. Wydawnictwa Naukowo-Techniczne, Warszawa, wydanie 2, 1989. [4] T. H. Cormen, C. E. Leiserson, R. L Rivest. Wprowadzenie do algorytmów. Wydawnictwa Naukowo-Techniczne, Warszawa, 1997. [5] L. Banachowski, K. Diks, W. Rytter. Algorytmy i struktury NJ/A+SD/2
NJ/A+SD/3 danych. Wydawnictwa Naukowo-Techniczne, Warszawa, 1996. [6] M. M. Sysło, N. Deo, J. Kowalik. Algorytmy optymalizacji dyskretnej. Państwowe Wydawnictwa Naukowe, Warszawa, 1993. [7] D. Harel. Rzecz o istocie informatyki. Algorytmika. Wydawnictwa Naukowo-Techniczne, Warszawa, 1992. [8] L. Banachowski, A. Kreczmar, W. Rytter. Analiza algorytmów i struktur danych. Wydawnictwa Naukowo-Techniczne, Warszawa, 1989. [9] L. Banachowski, A. Kreczmar. Elementy analizy algorytmów. Wydawnictwa Naukowo-Techniczne, Warszawa, 1982. [10] D. E. Knuth. Sztuka Programowania, wolumen I III. Wydawnictwa Naukowo-Techniczne, 2002.
Dynamiczne struktury danych Listy FIFO Stos Kolejki Listy dwukierunkowe Listy cykliczne Drzewa Drzewa binarne, z porzadkiem, dwukierunkowe Drzewa zrównoważone (później... ) NJ/A+SD/4
Grafy i ich reprezentacje (macierz sasiedztwa, listy sasiedztwa, tablica sasiedztwa) NJ/A+SD/5
NJ/A+SD/6 Struktura listy w Pascalu 1 type 2 l i s t a = ^ e l L i s t y ; 3 e l L i s t y = 4 record 5 klucz : integer ; 6 nast : l i s t a 7 end ; 2 3 4 5
NJ/A+SD/7 Struktura listy w C 1 struct e l { 2 i n t klucz ; 3 struct e l nast ; 4 } ; 5 6 typedef struct e l e l L i s t y ; 7 typedef e l L i s t y l i s t a ; 2 3 4 5
NJ/A+SD/8 Stworzenie elementu listy w Pascalu 1 var 2 p : l i s t a ; 3... 4 new( p ) ; 5 p ^. klucz := 13; 6 p ^. nast := NIL ; 13
NJ/A+SD/9 Usunięcie elementu listy w Pascalu 1 dispose ( p ) ; 2 p := NIL ;
NJ/A+SD/10 Stworzenie elementu listy w C 1 l i s t a l =0; / / badź: ellisty *l; 2 3 l = malloc ( sizeof ( e l L i s t y ) ) ; 4 l >klucz = 13; 5 l >nast = 0; 13
NJ/A+SD/11 Usunięcie elementu listy w C 1 f r e e ( l ) ; 2 l =0;
NJ/A+SD/12 1 var Połaczenie dwóch elementów p i q w listę (Pascal) 2 p, q : l i s t a ; 3... 4 new( p ) ; 5 p ^. klucz := 3; 6 p ^. nast := NIL ; 7 new( q ) ; 8 q ^. klucz := 13; 9 q ^. nast := p ; 10 { q pierwszy, p d r u g i } 13 3
NJ/A+SD/13 Połaczenie dwóch elementów p i q w listę (C) 1 e l L i s t y p=0, q=0; 2 3 p = malloc ( sizeof ( e l L i s t y ) ) ; 4 p >klucz = 3; 5 p >nast = 0; 6 q = malloc ( sizeof ( e l L i s t y ) ) ; 7 q >klucz = 13; 8 q >nast = p ; 13 3
NJ/A+SD/14 Stworzenie listy elementów: 1, 2, 3, 4,..., n (C) 1 e l L i s t y l =0, p=0; 2 i n t n=5; 3 while ( n ){ 4 p = malloc ( sizeof ( e l L i s t y ) ) ; 5 p >klucz = n+1; 6 p >nast = l ; 7 l = p ; 8 } 1 2 3 4 5
NJ/A+SD/15 Usunięcie pierwszego elementu listy l (Pascal) 1 procedure DelEl ( var l : l i s t a ) ; 2 var p : l i s t a ; 3 begin 4 i f l <>NIL then 5 begin 6 p := l ; 7 l := l ^. nast ; 8 dispose ( p ) 9 end 10 end ; 1 2 3 4 5
NJ/A+SD/16 Usunięcie pierwszego elementu listy l (C) 1 void UPeL( l i s t a l ) { / / wsk. na listę! 2 l i s t a p ; 3 i f ( l!= 0 ) { 4 p = l ; 5 l = ( l ) >nast ; / / lub p->nast 6 f r e e ( p ) ; 7 } 8 } 1 2 3 4 5
Usunięcie ostatniego elementu listy l (Pascal) 1 2 3 4 5 1 procedure DelLastEl ( var l : l i s t a ) ; 2 var t : l i s t a ; 3 begin 4 i f l <>NIL then 5 i f l ^. nast = NIL then 6 begin 7 dispose ( l ) ; 8 l := NIL ; 9 end NJ/A+SD/17
NJ/A+SD/18 10 else 11 begin 13 t := l ; 14 while t ^. nast ^. nast <>NIL do 15 t := t ^. nast ; 16 dispose ( t ^. nast ) ; 17 t ^. nast := NIL ; 18 19 end 20 end ;
NJ/A+SD/19 Usunięcie ostatniego elementu listy l (C) 1 2 3 4 5 1 void UOeL( l i s t a l ) { / / wsk. na listę! 2 i f ( l == 0) return ; 3 while ( ( l ) >nast ) 4 l = &( l ) >nast ; 5 f r e e ( l ) ; 6 l =0; / / nowy koniec listy! 7 }
NJ/A+SD/20 Zwolnienie całej listy l (Pascal) 1 2 3 4 5 1 procedure DisposeList ( var l : l i s t a ) ; 2 var t : l i s t a ; 3 begin 4 while l <>NIL do 5 begin 6 t := l ^. nast ; 7 dispose ( l ) ; 8 l := t ; 9 end end ;
NJ/A+SD/21 Lista dwukierunkowa (Pascal) 1 2 3 4 1 type 2 l i s t a C = ^ e l L i s t y C ; 3 e l L i s t y C = 4 record 5 klucz : integer ; 6 nast : l i s t a C ; 7 pop : l i s t a C 8 end ;
NJ/A+SD/22 Lista dwukierunkowa cykliczna (Pascal) 1 2 3 4 1 type 2 l i s t a C = ^ e l L i s t y C ; 3 e l L i s t y C = 4 record 5 klucz : integer ; 6 nast : l i s t a C ; 7 pop : l i s t a C 8 end ;
NJ/A+SD/23 Usunięcie elementu z l. cyklicznej (Pascal) 1 2 3 4 1 3 4 2 1 3 4
NJ/A+SD/24 1 procedure UsunElListyC ( var l : l i s t a C ) ; 2 var p : l i s t a C ; 3 begin 4 i f l <>NIL then 5 i f l = l ^. pop then 6 begin 7 dispose ( l ) ; l := NIL ; 8 end 9 else begin 10 p := l ; 11 l ^. pop ^. nast := l ^. nast ; 12 l ^. nast ^. pop := l ^. pop ; 13 l := l ^. nast ; 14 dispose ( p ) 15 end 16 end ;
NJ/A+SD/25 Dodanie elementu do l. cyklicznej (Pascal) 1 3 4 2 1 3 4 2
NJ/A+SD/26 1 3 4 2
1 procedure DodElListaC ( var l : l i s t a C ; klucz : integer ) ; 2 { doda za l! } 3 var 4 p : l i s t a C ; 5 n : l i s t a C ; 6 begin 7 new( p ) ; 8 p ^. klucz := klucz ; 9 i f l =NIL then 10 begin 11 l := p ; 12 p ^. pop := p ; 13 p ^. nast := p 14 end 15 else 16 begin NJ/A+SD/27
NJ/A+SD/28 17 n := l ^. nast ; 19 p ^. pop := l ; 20 p ^. nast := n ; 21 l ^. nast := p ; 22 n ^. pop := p ; 23 end 24 end ;
Dodanie elementu do l. cyklicznej (Pascal) 1 DodElListaC ( l, 1 ) ; 2 DodElListaC ( l, 2 ) ; 3 DodElListaC ( l, 3 ) ; 4 DodElListaC ( l, 4 ) ; 5 DispListCTeX ( l, a ) ; 6 UsunElListyC ( l ) ; 7 DispListCTeX ( l, a ) ; 8 UsunElListyC ( l ) ; 9 DispListCTeX ( l, a ) ; 10 UsunElListyC ( l ) ; 11 DispListCTeX ( l, a ) ; 12 UsunElListyC ( l ) ; NJ/A+SD/29
NJ/A+SD/30 13 DispListCTeX ( l, a ) ; 1 4 3 2 4 3 2 3 2 2
NJ/A+SD/31 Wypisuje elementy l. cyklicznej (Pascal) 1 procedure DispListC ( l : l i s t a C ) ; 2 var t : l i s t a C ; 3 begin 4 i f l <>NIL then 5 begin 6 t := l ; 7 repeat 8 write ( t ^. klucz ) ; 9 t := t ^. nast ; 10 i f t <> l then write ( > ) 11 u n t i l t = l ; 12 end 13 end ;
NJ/A+SD/32 Usuwanie l. cyklicznej (Pascal) 1 procedure DisposeListC ( var l : l i s t a C ) ; 2 var 3 t : l i s t a C ; 4 begin 5 while l <>NIL do 6 UsunElListyC ( l ) ; 7 end ;
FIFO,LIFO/Stos, kolejki priorytetowe Koncepcja wartownika dla list FIFO fist in first out wystarczy dobrze używać listy... dodaj do kolejki O(1) zdjać z kolejki O(1) dodajemy na koniec kolejki, zdejmujemy element-głowę Stos = LIFO last in first out wystarczy dobrze używać listy... dołóż na stos O(1) zdjać ze stosu O(1) NJ/A+SD/33
NJ/A+SD/34 dodawanie/zdejmowanie na/z poczatek/-ku listy kolejka priorytetowa Zadanie: pola węzła: klucz, priorytet i nast! wstawianie zgodnie z priorytetem zdejmowanie elementu o najwyższym priorytecie zmiana priorytetu, usuwanie elementu Wykorzystać stos do wyznaczania wyrażeń zapisanych w odwrotnej notacji polskiej (ONP). 3 4 + 2 *
Drzewa NJ/A+SD/35
NJ/A+SD/36 A B C D E F G I J K J K L M
NJ/A+SD/37 (a+b/c) (d e f) a b c / + d e f + a / b c d e f + a / d b c e f
NJ/A+SD/38 Drzewo z porzadkiem 44 23 58 6 31 56 78 27 35 60 99
NJ/A+SD/39 Reprezentacja drzewa (Pascal) Drzewo binarne 1 type 2 drzewob = ^wdrzewab ; 3 wdrzewab = 4 record 5 klucz : integer ; 6 lewy : drzewob ; 7 prawy : drzewob 8 end ;
NJ/A+SD/40 Drzewo o dowolnej liczbie gałęzi 1 type 2 drzewo = ^wdrzewa ; 3 wdrzewa = 4 record 5 klucz : integer ; 6 d z i e c i : l i s t a ; 7 end ;
NJ/A+SD/41 Węzły z info o przodku 1 type 2 drzewob = ^wdrzewab ; 3 wdrzewab = 4 record 5 klucz : integer ; 6 lewy : drzewob ; 7 prawy : drzewob 8 o j c i e c : drzewob 9 end ;
NJ/A+SD/42 Drzewo słownik z porzadkiem 1 type 2 drzewob = ^wdrzewab ; 3 wdrzewab = 4 record 5 klucz : integer ; 6 l i c z n i k : integer ; 7 lewy : drzewob ; 8 prawy : drzewob 9 end ;
NJ/A+SD/43 Podstawowe operacje słownikowe Dopisz Znajdź Usuń Maximum, Minimum, Poprzednik, Następnik
NJ/A+SD/44 1 procedure drukujdrzewo ( t : drzewob ; l : integer ) ; 2 var i : integer ; 3 begin 4 i f t <>NIL then 5 begin 6 drukujdrzewo ( t ^. lewy, l + 1 ) ; 7 for i :=1 to l do write ( ) ; 8 writeln ( t ^. klucz ) ; 9 drukujdrzewo ( t ^. prawy, l +1) 10 end 11 end ;
NJ/A+SD/45 1 procedure dopiszd ( var t : drzewob ; klucz : integer ) ; 2 begin 3 i f t =NIL then 4 begin 5 new( t ) ; 6 t ^. klucz := klucz ; t ^. l i c z n i k : = 1 ; 7 t ^. lewy := NIL ; t ^. prawy := NIL ; 8 end else 9 i f klucz < t ^. klucz then 10 dopiszd ( t ^. lewy, klucz ) else 11 i f klucz > t ^. klucz then 12 dopiszd ( t ^. prawy, klucz ) else 13 t ^. l i c z n i k := t ^. l i c z n i k +1; 14 end ;
NJ/A+SD/46 Drzewo z porzadkiem 44 23 58 6 31 56 78 27 35 60 99
NJ/A+SD/47 1 function znajdzd ( t : drzewob ; klucz : integer ) : drzewob ; 2 begin 3 i f t =NIL then 4 znajdzd : = NIL 5 else 6 i f klucz < t ^. klucz then 7 znajdzd := znajdzd ( t ^. lewy, klucz ) else 8 i f klucz > t ^. klucz then 9 znajdzd := znajdzd ( t ^. prawy, klucz ) else 10 znajdzd := t ; 11 end ;
NJ/A+SD/48 1 procedure zwolnijdrzewob ( var d : drzewob ) ; 2 begin 3 i f d<>nil then 4 begin 5 zwolnijdrzewob ( d ^. lewy ) ; 6 zwolnijdrzewob ( d ^. prawy ) ; 7 dispose ( d ) ; 8 d := NIL ; 9 end 10 end ;
1 procedure usund ( var t : drzewob ; klucz : integer ) ; 2 var 3 q : drzewob ; 4 procedure us ( var r : drzewob ) ; 5 begin 6 i f r ^. prawy<>nil then 7 us ( r ^. prawy ) 8 else 9 begin 10 q ^. klucz := r ^. klucz ; q ^. l i c z n i k := r ^. l i c z n i k ; 11 q := r ; { zmiana elementu do usunięcia } 12 r := r ^. lewy { przewieszenie przed usinięciem q } 13 end 14 end ; NJ/A+SD/49
NJ/A+SD/50 15 begin 17 i f t =NIL then writeln ( Nie ma... ) else 18 i f klucz < t ^. klucz then usund ( t ^. lewy, klucz ) else 19 i f klucz > t ^. klucz then usund ( t ^. prawy, klucz ) else 20 begin 21 q := t ; 22 i f q ^. prawy=nil then t := q ^. lewy else 23 i f q ^. lewy=nil then t := q ^. prawy else 24 us ( q ^. lewy ) ; 25 dispose ( q ) ; 26 end 27 end ;
type pdrzewob = ^drzewob; 1 procedure usund1 ( var t : drzewob ; klucz : integer ) ; 2 var 3 q : drzewob ; 4 procedure us ( r : pdrzewob ) ; 5 begin 6 while r ^ ^. prawy <> n i l do 7 r := @( r ^ ^. prawy ) ; 8 q ^. klucz := r ^ ^. klucz ; 9 q ^. l i c z n i k := r ^ ^. l i c z n i k ; 10 q := r ^ ; 11 r ^:= r ^ ^. lewy 12 end ; 13 NJ/A+SD/51
NJ/A+SD/52 14 begin 16 i f t =NIL then writeln ( Nie ma.... ) else 17 i f klucz < t ^. klucz then usund ( t ^. lewy, klucz ) else 18 i f klucz > t ^. klucz then usund ( t ^. prawy, klucz ) else 19 begin 20 q := t ; 21 i f q ^. prawy=nil then t := q ^. lewy else 22 i f q ^. lewy=nil then t := q ^. prawy else 23 us (@( q ^. lewy ) ) ; 24 dispose ( q ) ; 25 end 26 end ;
NJ/A+SD/53 Tak jest źle: 1 procedure us ( var r : drzewob ) ; 2 begin 3 while r ^. prawy <> NIL do 4 r := r ^. prawy ; 5 q ^. klucz := r ^. klucz ; 6 q ^. l i c z n i k := r ^. l i c z n i k ; 7 q := r ; 8 r := r ^. lewy 9 end ; "r" w lini 8 nie jest referencja właściwego pola rekordu (w wyniku działania wiersza 4).
1 begin 2 d := NIL ; 3 repeat 4 read ( n ) ; 5 dopiszd ( d, n ) ; 6 u n t i l n<=0; 7 writeln ; 8 drukujdrzewo ( d, 0 ) ; 9 10 usund ( d, 5 6 ) ; 11 drukujdrzewo ( d, 0 ) ; 12 usund ( d, 3 1 ) ; 13 drukujdrzewo ( d, 0 ) ; 14 NJ/A+SD/54
NJ/A+SD/55 15 w:= znajdzd ( d, 1 3 ) ; 17 i f w<>nil then 18 writeln ( JEST! ) 19 else 20 writeln ( NIE MA! ) ; 21 zwolnijdrzewob ( d ) ; 22 drukujdrzewob ( d, 0 ) ; 23 end.
Zadania Zaimplementować listę cykliczna w j. C. Zaimplementuj funkcje programu drzewo/słownik w j. C. Napisać algorytm, który dla N liczb wejściowych zbuduje drzewo możliwie dokładnie wyważone. Napisz funkcje wyświetlajace drzewo w układach (RLP wzdłużny), (LRP poprzeczny), (LPR wsteczny). R L P NJ/A+SD/56
Zaproponować algorytm wyliczania wszystkich możliwych drzew-wyrażeń z zastosowaniem nawiasów dla dowolnego wyrażenia postaci: L 1 op 1 L 2 op 2... op n 1 L n, np. dla: a+b/c d e f j.w., lecz tylko tych wyrażeń, które spełniaja równość: L 1 op 1 L 2 op 2... op n 1 L n = p, np.: 6 8+20 : 4 2 = 58 3248 : 16 3 315 156 2 = 600 NJ/A+SD/57
Napisz funkcję szukajac a węzeł o wskazanym kluczu w drzewie bez porzadku (rekurencyjnie). j.w. lecz nierekurencyjnie, ale wykorzystujac strukturę węzła ze wskaźnikiem na ojca. Napisz procedury wyznaczajace: wartość minimalna, maksymalna, poprzednia i następna dla drzew binarnych z porzadkiem. NJ/A+SD/58
NJ/A+SD/59 Grafy G = (V, E) V zbiór wierzchołków E zbiór krawędzi (elementami sa pary wierzchołków) Grafy: Zorientowane krawędzie sa parami uporzadkowane (v, w), tj, istnieje połaczenie v z w. Niezorientowane krawędź (v, w) oznacza połaczenie v z w i w z v
NJ/A+SD/60 A A B E C B E C D D
NJ/A+SD/61 A g f e a B E C b A 26 23 44 11 B E C 11 c d 15 d D D G = (V, E) V = {v i i = 1,..., m} E = {k i = ( v, w, d k ) k = 1,..., n}
Reprezentacje grafów NJ/A+SD/62
Macierz sasiedztwa, M[i, j] = 0/1: 1 2 4 3 Listy sasiedztwa: W1: 2 4 0 1 0 1 0 0 1 0 0 0 0 0 0 1 1 0 W2: 3 W3:. W4: 2 3 NJ/A+SD/63
NJ/A+SD/64 Reprezentacja tablicowa 1 2 1 5 2 7 3 0 4 3 4 8 5 2 6 6 4 0 7 3 0 8 2 9 9 3 0
NJ/A+SD/65 Terminologia około-grafowa v jest sasiadem w, gdy istnieje krawędź (v, w) Stopień wierzchołka: liczba sasiadów Droga/ścieżka: ciag krawędzi (v 1, v 2 ),(v 2, v3),...,(v k 1, v k ) Cykl: droga z pewnego wierzchołka v do v (musi składać się przynajmniej z jednej krawędzi!) Graf spójny: istnieje ścieżka pomiędzy każda para wierzchołków Drzewo: graf spójny bez cykli! Klika grafu G = (V, E): podzbiór V V taki, że dla każdej pary wierzchołków p, q V istnieje krawędź (p, q) E.
NJ/A+SD/66 Złożoność Złożoność rozmiar zadania Złożoność: Czasowa Pamięciowa Złożoność czasowa: czas pracy programu wyrażony jako funkcja rozmiaru zadania. Złożoność pamięciowa: zajętość pamięci przez program wyrażony jako funkcja rozmiaru zadania.
NJ/A+SD/67 Definicja Złożoność czasowa programu wykorzystujacego g(n) jednostek czasowych jest O( f(n)), jeśli istnieje stała c i g(n) c f(n), dla prawie wszystkich n (wszystkich z wyjatkiem skończonego zbioru wartości n). O( f(n)) jest rodzina funkcji spełniajacych powyższa definicję. g(n) = 3n 2 O(n 2 ) g(n) =.01n O(n) g(n) = n+44n 3 + n 1/2 O(n 3 ) O( f(n)) ma złożoność f(n) jest rzędu f(n)
NJ/A+SD/68 7 g(n) c f(n) 6 5 4 3 2 1 0 2 4 6 8 10 12 n
NJ/A+SD/69 g(n) = 1024 O(1) g(n) = 0.25 O(1) g(n) = n+ n 1 O(n) g(n) = n+ 1 log n O(n) Prawidłowy jest też zapis: 1 n = O(1) (odpowiednik matematycznego w: n 1 O(1)) Prawda jest, że: 1 n = O(n) 1 n = O(n2 ) 1 n = O(nk ) 5n = O(n) 5n = O(n 2 )
NJ/A+SD/70 5n+ O(n) = O(n) 5n+ O(n) = O(n 2 ) 5n+ O(n 2 ) =O(n) n 4 = 1 4 n4 + O(n 3 ) g(n) = n 3 + 5n 2 22n = O(n 3 ) n+1/ log n = O(n) n 2 + O(n) = O(n 2 ) n 2 + c O(n) = O(n 2 ) n 2 + O(n log n) = O(n 2 ) n(n+1) 2 = O(n 2 ) n(n+1) 2 0.5n 2 = O(n) n(n+1) 2 0.3n 2 = O(n 2 ) n+2 O(n 2 ) = O(n 2 ) n+log n O(n 2 ) = O(n 2 log n) log n n = O(1)
NJ/A+SD/71 g(n) = a k n k + a k 1 n k 1 +...+a 1 n+a 0 = O(n k ) dla a k > 0 33 2 n = O(2 n ) 2 n+2 + n 6 = O(2 n ) 2 n = O(3 n ) 3 n = O(2 n ) n = O( n) n = O(n) 3 n = O( n)
NJ/A+SD/72 Granice rozmiaru zadania vs. złożoność Max roz. zadania Złożoność 1s 1min 1h n 1000 6 10 4 3.6 10 6 n log n 140 4893 2.0 10 5 n 2 31 244 1897 n 3 10 39 153 2 n 9 15 21
NJ/A+SD/73 Wpływ 10-krotnego przyśpieszenia komputera na maksymalny rozmiar zadania Złożoność R.z.przed R.z.po n s 1 10s 1 n log n s 2 10s 2 (dla dużych s 2 ) n 2 s 3 3.16s 3 n 3 s 4 2.15s 4 2 n s 5 s 5 + 3.3
NJ/A+SD/74 Złożoność c.d. Złożoność pesymistyczna (z. czasowa) z. najgorszego przypadku. Złożoność średnia średnia z. po wszystkich danych rozmiaru n. Z. pesymistyczna nierzadko równa jest z. średniej.
NJ/A+SD/75 O, Θ i Ω O asymptotyczna granica górna O( f(n)) = {g(n) : c>0,n0 >0 n n0 0 g(n) c f(n)} Ω asymptotyczna granica dolna Ω( f(n)) = {g(n) : c>0,n0 >0 n n0 0 c f(n) g(n)} Θ asymptotycznie dokładne oszacowanie Θ( f(n)) = {g(n) : c1 >0,c 2 >0,n 0 >0 n n0 0 c 1 f(n) g(n) c 2 f(n)}
NJ/A+SD/76 10 8 c 2 f(x) g(n) c 1 f(x) 6 4 2 0 0 1 2 3 4 5 6 7 8 9 10 n
NJ/A+SD/77 Klasy P i NP Klasa P gdy algorytm ma złożoność wielomianowa. Klasa N P gdy algorytm nie ma złożoności wielomianowej.
NJ/A+SD/78 Kryteria kosztów Jednorodne kryterium kosztów zakłada się, że jedna instrukcja wykonywana jest w jednej jednostce czasu zakłada się, że każdy rejestr wymaga jednej jednostki pamięci l(i) = 1 Logarytmiczne kryterium kosztów [uwzględnienie długości słowa komputera] l(i) = log i +1 i > 0 1 i = 0
NJ/A+SD/79 Złożoność Kołmogorowa i Levina Złożoność Kołmogorowa K U (x) = min p { l(p) : program p prints x}. (1) Złożoność Levina Kt U (x) = min p { l(p)+log t(p, x) : program p prints x in t(p, x)}. (2)
NJ/A+SD/80 Warunkowa złożoność Levina Kt U (w x, φ) = min{l(p)+log t(p, x) : program p p prints w and test φ(w) = x in t(p, x)}. (3)
NJ/A+SD/81 Zadania Wyznaczyć złożoność różnych funkcji dotyczacych operowania na listach i drzewach. Jaka jest złożoność wyznaczania wektora o maksymalnej normie ze zbioru S = {x i : i = 1,..., n, x R d }?
NJ/A+SD/82 Zadanie sortowania Wejście: zbiór liczb a 1,..., a n Wyjście: ciag liczb spełniajacy a i1... a in
NJ/A+SD/83 Algorytmy sortowania i ich złożoności Trudno gorzej niż O(n 2 ) Aż do... O(n)!!! Sortowanie za pomoca: tablic, drzew, kolejek
NJ/A+SD/84 O(n 2 ) przykłady Sortowanie przez proste wstawianie Sortowanie przez wstawianie połówkowe (ZADANIE) Sortowanie przez proste wybieranie Sortowanie babelkowe
NJ/A+SD/85 1 procedure ProsteWstawianie ; 2 begin 3 for i :=2 to n do 4 begin 5 x := a [ i ] ; a [ 0 ] : = x ; j := i 1; 6 while x < a [ j ] do 7 begin 8 a [ j +1]:=a [ j ] ; j := j 1; 9 end 10 a [ j +1]:= x ; 11 end 12 end ; Wynik pośredni dla i-tej iteracji pętli f or: a 1,..., a i 1 (posortowane) a i,..., a n (nieposortowane)
NJ/A+SD/86 1 procedure ProsteWybieranie ; 2 begin 3 for i :=1 to n 1 do 4 begin 5 k := i ; x := a [ i ] ; 6 for j := i +1 to n do 7 i f a [ j ] < x then 8 begin k := j ; x := a [ j ] ; 9 end ; 10 a [ k ] : = a [ i ] ; a [ i ] : = x ; 11 end 12 end ; Najmniejszy na poczatek, na druga pozycję najmniejszy z pozostałych, itd.
NJ/A+SD/87 1 procedure SortowanieBabelkowe ; 2 begin 3 for i :=2 to n do 4 begin 5 for j := n downto i do 6 i f a [ j 1] > a [ j ] then 7 begin 8 x := a [ j 1]; a [ j 1]:= a [ j ] ; a [ j ] : = x ; 9 end 10 end 11 end ; Duże babelki szybciej wychodza na powierzchnię...
NJ/A+SD/88 Algorytmy sortujace w O(n log n) Złożoność średniego przypadku, a pesymistyczna złożoność Sortowanie przez kopcowanie Szybkie sortowanie Drzewa z porzadkiem Sortowanie przez łaczenie (ZADANIE)
NJ/A+SD/89 Sortowanie przez kopcowanie Algorytm in-situ, jak poprzednie, ale o złożoności O(n log n). Warunek kopca: R L i R P R 22 L P 13 7
NJ/A+SD/90 Kopiec 16 1 14 2 10 3 8 4 7 5 9 6 3 7 2 8 4 9 1 10
NJ/A+SD/91 Kopiec c.d Reprezentacja: drzewo lub tablica PARENT[i] = i/2 LEFT[i] = 2i RIGHT[i] = 2i+1
NJ/A+SD/92 Heapify O(log n) 16 1 4 2 10 3 14 4 7 5 9 6 3 7 2 8 8 9 1 10
NJ/A+SD/93 16 1 14 2 10 3 4 4 7 5 9 6 3 7 2 8 8 9 1 10
NJ/A+SD/94 16 1 14 2 10 3 8 4 7 5 9 6 3 7 2 8 4 9 1 10
NJ/A+SD/95 1 procedure Heapify (A, i ) ; 2 begin 3 l :=LEFT ( i ) ; r :=RIGHT( i ) ; 4 i f l <= heapsize [ A ] and A [ l ] > A[ i ] 5 then l a r g e s t := l 6 else l a r g e s t := i ; 7 i f r <= heapsize [ A ] and A [ r ] > A[ l a r g e s t ] then 8 l a r g e s t := r ; 9 i f l a r g e s t <> i then 10 begin x :=A [ i ] ; A [ i ] : = A [ l a r g e s t ] ; A[ l a r g e s t ] : = x ; 11 Heapify (A, l a r g e s t ) ; 12 end 13 end ;
NJ/A+SD/96 Budowanie kopca 1 procedure BuildHeap ( A ) ; 2 begin 3 heapsize [ A ] : = l e n g t h [ A ] ; 4 for i := length[a]/2 downto 1 do 5 Heapify (A, i ) 6 end ; kopce, kopce kopców,...
NJ/A+SD/97 4 1 1 2 3 3 2 4 16 5 9 6 10 7 14 8 8 9 7 10
NJ/A+SD/98 4 1 1 2 3 3 2 4 16 5 9 6 10 7 14 8 8 9 7 10
NJ/A+SD/99 4 1 1 2 3 3 14 4 16 5 9 6 10 7 2 8 8 9 7 10
NJ/A+SD/100 4 1 1 2 10 3 14 4 16 5 9 6 3 7 2 8 8 9 7 10
NJ/A+SD/101 4 1 16 2 10 3 14 4 7 5 9 6 3 7 2 8 8 9 1 10
NJ/A+SD/102 16 1 14 2 10 3 8 4 7 5 9 6 3 7 2 8 4 9 1 10
NJ/A+SD/103 Złożoność procedury BuildHeap(A) Heapify O(h) h wysokość kopca n elementowy kopiec ma co najwyżej n/2 h+1 pod-kopców wysokości h Całość: mamy jednak: ostatecznie: log n h=0 ( n log n 2 h+1 O(h) = O n h=0 h=0 h 2 h = 1/2 (1 1/2) 2 = O(n) ) h 2 h
NJ/A+SD/104 Sortowanie przez kopcowanie Zbudowanie kopca Korzeń = max Usuniecie korzenia (na koniec... ) i powtarzanie... [zamiana max i el. ostatnim, i skrócenie tablicy A]
NJ/A+SD/105 1 procedure HeapSort ( A ) ; 2 begin 3 BuildHeap (A ) ; 4 for i := l e n g t h (A) downto 2 do 5 begin 6 x :=A [ 1 ] ; A [ 1 ] : = A [ i ] ; A [ i ] : = x ; 7 heapsize (A) : = heapsize (A) 1; 8 Heapify (A, 1 ) ; 9 end 10 end ; Ostateczna złożoność: O(n log n)
Zadania Prześledzić na kilku około 10 elementowych tablicach omówione algorytmy sortowania. Opracuj algorytm sortowania przez wstawianie połówkowe. Opracuj algorytm sortowania przez łaczenie. Zaproponować wersję iteracyjna rekurencyjnej procedury Heapify. Analiza złożoności algorytmów (porównaj liczby porównań, przestawień, poszczególnych pod-etapów różnych algorytmów). Prześledź zachowanie się algorytmów sortowania dla najlepszych i najgorszych przypadków. NJ/A+SD/106
Co można powiedzieć o złożonościach O, Ω, Θ dla algorytmów sortowania przez przestawianie, wybór i sortowanie babelkowe? NJ/A+SD/107
NJ/A+SD/108 Algorytm szybkiego sortowania (Quicksort) Dziel i zwyciężaj! 1. Dziel na dwie części A i B. A ma elementy nie większe od x, B ma większe od x. 2. Zwyciężaj: sortuj A i B. 3. Łaczenie A i B.
NJ/A+SD/109 1 procedure QSort (A, p, r ) ; 2 begin 3 i f p < r then 4 begin 5 q := P a r t i t i o n (A, p, r ) ; 6 QSort (A, p, q ) ; 7 QSort (A, q+1, r ) ; 8 end 9 end ; A p,..., A q A q+1,..., A r A p,..., A q A q+1,..., A r A p,..., A q A q+1,..., A r... A p A p+1 A p+2... A r 1 A r
NJ/A+SD/110 1 function P a r t i t i o n (A, p, r ) ; 2 begin 3 A [ p ] A[ Random[ p, r ] ] ; 4 x :=A [ p ] ; 5 i := p 1; j := r +1; 6 do 7 do j := j 1; while A[ j ] > x ; 8 do i := i +1; while A[ i ] < x ; 9 i f i < j then A [ i ] A[ j ] ; 10 while i < j ; 11 return j ; 12 end ; A[p, i] x A[j, r]
NJ/A+SD/111 Złożoność szybkiego sortowania Złożoność funkcji Partition: Θ(n) Najlepszy przypadek: Θ(n log n) Najgorszy przypadek: Θ(n 2 ) Średni przypadek: Θ(n log n)
NJ/A+SD/112 Najlepszy przypadek: Θ(n log n) n n/2 n/2 n/4 n/4 n/4 n/4
NJ/A+SD/113 Ponieważ: Koszt całościowy każdego z poziomów: Θ(n) Liczba poziomów: log n T(n) = 2T(n/2)+Θ(n) = Θ(n log n)
NJ/A+SD/114 Najgorszy przypadek: Θ(n 2 ) n 1 n 1 1 n 2 1 n 3 Ponieważ: Koszt całościowy każdego z poziomów: Θ(n) Liczba poziomów: n T(n) = T(n 1)+Θ(n) = n i=1 Θ(i) T(n) = Θ( n i=1 i) T(n) = Θ(n 2 ) 1 n 4
NJ/A+SD/115 Średni przypadek: Θ(n log n) Niech T(n) będzie średnim czasem sortowania przez QS Wtedy czasy wywołań rekurencyjnych to T(i) i T(n i) Każde i jest jednakowo prawdopodobne wybrane losowo Wykonanie Partition kosztuje Θ(n) Mamy więc: T(n) = 1 n n 1 i=1 [T(i)+T(n i)]+θ(n) jako że każde T(j) w występuje 2 razy: T(n) = 2 n n 1 i=1 T(i)+Θ(n)
NJ/A+SD/116 Przez indukcję chcemy pokazać: T(n) an log n+b+θ(n) a, b > 0 Dla n = 1 prosto znaleźć odpowiednie a, b! Dla n > 1 T(n) 2 n n 1 k=1 (ak log k+b)+θ(n) = 2a n n 1 k log k+2b n 1 n k=1 + Θ(n)
NJ/A+SD/117 Skorzystamy z: n 1 k log k 1 2 n2 log n 1 8 n2 k=1 Mamy więc: T(n) 2a n [ 1 2 n2 log n 1 ] 8 n2 + 2b n 1 n + Θ(n) an log n a 4 n+2b+θ(n) = an log n+b+ [ an 4 + b+θ(n) ] an log n+b dla dużego a
NJ/A+SD/118 Wróćmy do: n 1 k log k 1 2 n2 log n 1 8 n2 k=1 n 1 k log k = k=1 n/2 1 k=1 k log k+ n 1 k log k k= n/2 Wiemy, że: log n/2 n/2 1 k=1 k n/2 1 k=1 k log k log n n 1 k k= n/2 n 1 k log k k= n/2
NJ/A+SD/119 n 1 k log k (log n 1) k=1 n/2 1 k=1 k+log n n 1 k k= n/2 = log n n 1 k k=1 n/2 1 k=1 k 1 2 n(n 1) log n 1 2 n 2 ( n 2 1 ) 1 2 n2 log n 1 8 n2
NJ/A+SD/120 Algorytmy sortowania O(n) Sortowanie przez zliczanie Sortowanie kubełkowe Sortowanie przez zliczanie Założenia: A i N 1 A i k
NJ/A+SD/121 IDEA: Jeśli wiemy ile jest elementów mniejszych od pewnego A i, wiemy gdzie (na której pozycji) powinien być umieszczony element A i w tablicy posortowanej: {k : A k < A i, A k A} =???
NJ/A+SD/122 1 function S o r t Z l i c z a n i e (A, B, k ) ; { A-wejście, B-wyjście } 2 begin 3 for i :=1 to k do 4 C[ i ] : = 0 5 for i :=1 to l e n g t h [ A ] do 6 C[ A [ i ] ] : = C[ A [ i ] ] + 1 { z l i c z a n i e } 7 for i :=2 to k do 8 C[ i ] : =C[ i ]+C[ i 1] { i l e mniejszych od i } 9 for i := l e n g t h [A] downto 1 do 10 begin 11 B [C[A[ i ] ] ] : = A [ i ] { w odpowiednie B [. ] A [ i ] } 12 C[ A [ i ] ] : = C[ A[ i ]] 1 13 end 14 end ;
NJ/A+SD/123 A: 1 2 3 4 5 6 7 8 3 6 4 1 3 4 1 4 B: 1 2 3 4 5 6 7 8 4 C: 1 2 3 4 5 6 2 0 2 3 0 1 C[A[i]]:= C[A[i]]+1 B: 1 2 3 4 5 6 7 8 1 4 C: 1 2 3 4 5 6 2 2 4 7 7 8 B: 1 2 3 4 5 6 7 8 1 1 3 3 4 4 4 6 C[i]:=C[i]+C[i-1] B[C[A[i]]]:=A[i]
NJ/A+SD/124 Złożoność sortowania przez zliczanie Wiersze 3 4: O(k) Wiersze 5 6: O(n) Wiersze 7 8: O(k) Wiersze 9 13: O(n) Razem O(k)+ O(n) = O(n+k) = O(n), gdy k = O(n) Stabilny = liczby o tej samej wartości w tej samej kolejności w A i w B!
NJ/A+SD/125 Algorytm sortowania kubełkowego Średni czas: O(n) Założenia: A i [0, 1) i = 1,..., n A i maja rozkład jednostajny(!) IDEA: Kubełki = dzielimy [0, 1) na n podprzedziałów.
NJ/A+SD/126 A B 1 0.21 2 0.93 3 0.02 4 0.27 5 0.44 6 0.41 7 0.88 8 0.54 9 0.69 10 0.42 0 0.02 1 2 0.27 0.21 3 4 0.42 0.41 0.44 5 0.54 6 0.69 7 8 0.88 9 0.93
NJ/A+SD/127 1 function SortKubelkowe ( A ) ; 2 begin 3 n := l e n g t h [ A ] 4 for i :=1 to n do 5 wstaw A [ i ] do listy B [ na[i] ] 6 for i :=0 to n 1 do 7 sortuj B [ i ] przez wstawianie 8 połacz listy B [ 0 ].. B[ n 1] 9 end ;
NJ/A+SD/128 Oczekiwana złożoność sortowania kubełkowego w. 3 5 O(n) w. 6 7??? n i zmienna losowa oznaczajaca liczbę elementów w B[i]. Sortowanie z w. 7 działa w O(p 2 ). Czas oczekiwany posortowania B[i] wynosi: E[O(n 2 i )] = O(E[n2 i ]) Wtedy oczekiwany czas wykonania w. 6 7: n 1 i=0 O(E[n 2 i ]) = O ( n 1 i=0 E[n 2 i ] )
NJ/A+SD/129 Prawdopodobieństwo, że element trafi do B[i] wynosi 1/n (1/n rozmiar przedziału B[i]). Zmienna n i ma rozkład dwumianowy. P(n i = k) = b(k; n, p) E[n i ] = np = 1 Var[n i ] = np(1 p) = 1 1/n Wiemy, że Var[n i ] = E[n 2 i ] E2 [n i ] E[n 2 i ] = Var[n i]+e 2 [n i ] = 1 1 n + 12 = 2 1 n = Θ(1) O ( n 1 i=0 E[n 2 i ] ) = nθ(1) = Θ(n)
NJ/A+SD/130 Zadania Zaimplementuj 3 różne algorytmy szybkiego sortowania różniace się sposobem wyboru elementu podziału pierwszy element (A[p]), losowy element, mediana z 3 losowo wybranych elementów. Porównaj zachowania się algorytmów dla losowych ciagów, jak i uporzadkowanych (częściowo też). Jak usprawnić algorytm sortowania kubełkowego, aby jego pesymistyczny czas wynosił O(n log n)?
Statystyka pozycyjna Wybór k-tego najmniejszego elementu Mediana k = n 2 mediana Rozwiazanie Sortowanie drogie... O(n log n) Dziel i zwyciężaj O(n) NJ/A+SD/131
NJ/A+SD/132 Idea: Podziel S na trzy zbiory S 1 (< m), S 2 (= m), S 3 (> m). Aby czas był liniowy długości S 1 i S 3 musza być ułamkami długości S. Powtarzamy rekurencyjnie...
NJ/A+SD/133 Jak znaleźć m, dla którego liczba wartości mniejszych i większych będzie ułamkiem S? Podzielić S na n 5 zbiorów. Posortować podzbiory (ile to kosztuje?).
NJ/A+SD/134 Niech M będzie ciagiem median posortowanych ciagów (M ma n/5 elementów). Znajdź medianę m ciagu M (T(n/5) szybciej niż T(n)... ) Podziel S na trzy zbiory S 1 (< m), S 2 (= m), S 3 (> m). ciag median
NJ/A+SD/135 Gdzie jest k-ty element? W S 1, S 2 czy S 3? Jeśli S 1 k S 1 ma k-ty element, w p.p. Jeśli S 1 + S 2 k S 2 ma k-ty element = m! w p.p. k-ty element jest w S 3, jako k S 1 S 2 element w S 3.
NJ/A+SD/136 1 function Select ( k, S ) ; 2 i f S < 50 then begin 3 s o r t u j S 4 return k-ty najmniejszy 5 end 6 else begin 7 podziel S na S /5 możliwie równych ciagów 8 sortuj każdy taki ciag 9 niech M będzie ciagiem median powyższych podciagów 10 m:= Select ( M /2, M) 11 Podziel S na S 1 (< m),s 2 (= m),s 3 (> m) 12 i f S 1 >= k then return Select ( k,s 1 ) 13 else 14 i f S 1 + S 2 >=k then return m 15 else return Select ( k S 1 S 2, S 3 ) 16 end
NJ/A+SD/137 Analiza algorytmu Załóżmy, że dla ciagu długości n algorytm wykonuje T(n) operacji. w. 3 O(1) w. 8 O(n) w. 9 n/5 w. 10 T(n/5) w. 11 O(n) w. 12 i 15 T( S 1 ) i T( S 3 ) odpowiednio (wykonywane jest tylko jedno z nich!)
NJ/A+SD/138 elementy m m ciag M (uporzadkowany) elementy m
NJ/A+SD/139 M ma co najwyżej n/10 elementów m Wtedy S 1 ma co najwyżej n 3 n/10 elementów. Dla n 50 S 1 < 3n/4. Podobnie dla S 3. Czyli w. 12 i 15 wymagaja nie więcej niż T(3n/4) Mamy więc: T(n) cn dla n < 50 T(n) T(n/5)+T(3n/4)+cn dla n 50 Można (przez indukcję) pokazać, że T(n) 20cn.
NJ/A+SD/140 Algorytm wyboru II 1 function Select2 ( k, S ) ; 2 i f S =1 then return S [ 1 ] ; 3 else 4 begin 5 m := S [ Random( 1, n ) ] ; 6 Podziel S na S 1 (< m),s 2 (= m),s 3 (> m) 7 i f S 1 >= k then return Select2 ( k,s 1 ) 8 else 9 i f S 1 + S 2 >= k then return m 10 else return Select2 ( k S 1 S 2,S 3 ) 11 end
NJ/A+SD/141 Złożoność średniego przypadku algorytmu Select2 Każdy indeks i wybranego elementu m w w.5 (po wykonaniu partition w.6) jest tak samo prawdopodobny. Jeśli k < i to wykonywana jest funkcja Select dla ciagu i 1 elementowego. Jeśli k > i to dla n i. Stad oczekiwany koszt w.7 lub w.10 uśredniamy po różnych możliwych wartościach i dla zadanego k: 1 n [ k 1 i=1 T(n i)+ ] n T(i 1) i=k+1 = 1 n [ n 1 T(i)+ i=n k+1 n 1 i=k T(i) ]
NJ/A+SD/142 Wtedy dla T(n) mamy: T(n) cn+max k { 1 n [ n 1 T(i)+ i=n k+1 n 1 i=k T(i) ]} Przez indukcję otrzymujemy: T(n) 4cn.
Zadania Zapisz ostateczna postać wiersza 11 funkcji Select. Przeanalizuj działanie funkcji Select dla wybranego ciagu długości około 8 elementów. W wierszu 7 na stronie 134 dzielimy S na podciagi długości 5. Jak algorytm zachowa się dla innych liczb (3,4,7,11,etc.)? Co możesz powiedzieć o algorytmie szybkiego sortowania w którym procedura Partition dzieliła by zbiór względem mediany? Co dzieje się ze złożonościa średniego przypadku, a co ze złożonościa najgorszego przypadku? Udowodnić przez indukcję, że dla algorytmu Select mamy: T(n) 20cn. NJ/A+SD/143