. Typy złożoności obliczeniowej Wykład Grafy, algorytmy grafowe Typ złożoności oznaczenie n Jedna operacja trwa µs 5 logarytmiczna lgn. s. s.7 s liniowa n. s.5 s. s Logarytmicznoliniowa nlgn. s.8 s.4 s kwadratowa n. s.5 s. s Wielowamianowa n k. s.8 s s (k-stopien k= wielomianu) wykładnicza n.4 s 5. lat 4.87* lat wykładnicza n! n!.88 s.* 8 lat.9* 44 lat Zofia Kruczkiewicz, USM, Algorytmy i struktury danych, Wykład,
. Reprezentacje grafu Macierz incydencji w programach przedstawiana jako tablica dwuwymiarowa, gdzie indeksy wierszy reprezentują numery wierzchołków, a indeksy kolumn oznaczają numery krawędzi. Elementy równe oznaczają krawędzie oznaczone numerami kolumn incydentne z wierzchołkiem oznaczonym numerem wiersza a e b c f 5 d 4 g Lista incydencji jest efektywną postacią macierzy incydencji w programach reprezentowana przez: tablice struktur, które zawierają numer wierzchołka oraz wskaźnik na listę krawędzi incydentnych do danych wierzchołków; lista krawędzi incydentnych zawiera elementy, które mają numer wierzchołka i wskaźnik na taki element (a) lista elementów zawierających numer wierzchołka, wskaźnik na listę krawędzi incydentnych do danych wierzchołków (jw) oraz wskaźnik na taki element (b) a (a) a b c d e f g 4 5 a (b) a b e a b e b c g f b c g f 4 c d 4 c d 5 d e 5 d e g f g f Własności macierzy incydencji:. Jeśli każda krawędź jest incydentna do dwóch wierzchołków, to w każdej kolumnie mamy tylko dwie jedynki. Wiersz z samych zer reprezentuje wierzchołek izolowany. Pętla jest reprezentowana przez jedną jedynkę 4. Krawędzie równoległe tworzą dwie identyczne kolumny w macierzy 5. Jeśli graf jest niespójny i składa się np. z składowych g i g, to można je wyrazić za pomocą części macierzy, które nie mają wspólnych wierszy i kolumn. wa grafy są izomorficzne, jeśli różnią się tylko permutacją wierszy i kolumn, czyli jedynie różnymi etykietami wierzchołków i krawędzi Zofia Kruczkiewicz, USM, Algorytmy i struktury danych, Wykład,
Macierz sąsiedztwa grafu nieskierowanego - w programach przedstawiana jako tablica dwuwymiarowa, gdzie indeksy wierszy i kolumn reprezentują numery wierzchołków, a wartości elementów równe oznaczają krawędź łącząca wierzchołki określone numerem wiersza i kolumny a e b c 5 d 4 f Lista sąsiedztwa jest efektywną pamięciowo postacią macierzy sąsiedztwa w programach reprezentowana przez: tablice struktur, które zawierają numer wierzchołka oraz wskaźnik na listę wierzchołków sąsiadującymi z danym wierzchołkiem; lista wierzchołków sąsiadujących zawiera elementy, które mają numer wierzchołka oraz wskaźnik na taki element (a) lista elementów zawierających numer wierzchołka, wskaźnik na listę wierzchołków sąsiadującymi z danym wierzchołkiem (jw) oraz wskaźnik na taki element (b) (a) 4 5 4 5 (b) 5 5 4 4 4 5 4 5 5 4 5 4 Własność macierzy sąsiedztwa. Elementy wzdłuż głównej przekątnej są równe, jeśli graf nie ma pętli, oraz jeśli ma pętle. Nie można wyrazić krawędzi równoległych. Wiersz i kolumny muszą być ustawione w tym samym porządku. Oznacza to, że przestawienie dwóch wierszy wymaga przestawienia odpowiadających kolumn 4. Jeśli graf jest niespójny i składa się np. z składowych g i g, to można je wyrazić za pomocą części macierzy, które nie mają wspólnych wierszy i kolumn Zofia Kruczkiewicz, USM, Algorytmy i struktury danych, Wykład,
Macierz sąsiedztwa grafu skierowanego - w programach przedstawiana jako tablica dwuwymiarowa, gdzie indeksy wierszy i kolumn reprezentują numery wierzchołków, a wartości elementów równe oznaczają krawędź łącząca wierzchołki określone numerem wiersza i kolumny a e b c 5 d 4 f 4 5 4 5 Lista sąsiedztwa jest efektywną pamięciowo postacią macierzy sąsiedztwa w programach reprezentowana przez: tablice struktur, które zawierają numer wierzchołka oraz wskaźnik na listę wierzchołków sąsiadującymi z danym wierzchołkiem (zgodnie z kierunkiem krawędzi); lista wierzchołków sąsiadujących zawiera elementy, które mają numer wierzchołka oraz wskaźnik na taki element (a) lista elementów zawierających numer wierzchołka, wskaźnik na listę wierzchołków sąsiadującymi z danym wierzchołkiem (zgodnie z kierunkiem krawędzi) oraz wskaźnik na taki element (b) Zofia Kruczkiewicz, USM, Algorytmy i struktury danych, Wykład, 4
. Algorytmy grafowe.. Przeszukiwanie grafu w głąb FS - algorytmy z powrotami Algorytmy z powrotami są wykorzystywane do rozwiązywania problemów, w których z określonego zbioru jest wybierana sekwencja obiektów tak, aby spełniała ona określone kryteria. Przykład Przeszukiwanie drzewa binarnego w sposób przedrostkowy jest przykładem przeszukiwania w głąb czyli przykładem algorytmu z powrotami (wykład 8) Przykład Wynikiem przeszukiwanie grafu w głąb jest las złożony z jednego lub wielu drzew przeszukiwania w głąb (gdy graf jest niespójny lub jest grafem skierowanym), który zawiera wszystkie wierzchołki grafu. G= {V, E}, gdzie V jest zbiorem wierzchołków (węzłów) i E zbiorem krawędzi IALY kolor nadawany nie odwiedzonym wierzchołkom SZARY kolor nadawany odwiedzonym wierzchołkom ZARNY kolor nadawany węzłowi, którego lista sąsiedztwa została odwiedzona wierzcholek { kolor; odwiedzony; czas_; czas_;} wierzcholek wierzcholki[v[g]] FS (G). dla każdego wierzchołka u należącego do V[G] { wierzcholki[u].kolor = IALY wierzcholki[u].odwiedzony = }. czas =. dla każdego wierzcholka u należącego do V[G] jeśli wierzcholki[u].kolor == IALY //nowy wierzchołek drzewa w lesie przeszukiwań to wywołaj FS_VISIT(u) // lub nowe drzewo poszukiwań FS_VISIT(u). wierzcholki[u].kolor = SZARY. wierzcholki[u].czas_ = ++czas. dla każdego wierzchołka v należącego do listy sąsiedztwa wierzchołka u { jeśli wierzcholki[v].kolor == IALY to wierzcholki[v].odwiedzony = u //u -poprzednik nie odwiedzonego następcy v FS_VISIT(v) } 4. wierzcholki[u].kolor = ZARNY 5. wierzcholki[u].czas_ = ++czas Zofia Kruczkiewicz, USM, Algorytmy i struktury danych, Wykład, 5
Graf skierowany: : krawędź drzewa przeszukiwania (krawędź (u, v), gdy odwiedzony został v), : krawędź powrotna (również dla krawędzi typu pętla łączy v z jego przodkiem u), F: krawędź w przód (łączy u z potomkiem v), : krawędź poprzeczna (prowadząca do innego drzewa poszukiwań w grafie skierowanym lub niespójnym lub łączy wierzchołki, z których jeśli tylko jeden nie jest przodkiem drugiego), () / () ( ) () / () / () () / () / () () /4 ( ) () / () () /4 () () / () () /4 () () / () () () () () /4 () / () 4() / () /4 () / () 4() / () /4 () / () 4() / () /4 () () / () 4() / () /4 () 7/ () / () 4() / () /4 () 7/ () / () 4() / (5) 8/ 7/ (5) 8/ 7/ (5) 8/9 7/ Zofia Kruczkiewicz, USM, Algorytmy i struktury danych, Wykład,
() /4 () / () 4() / () /4 () / (4) 4() / () /4 () / () 4() / () /4 (5) 8/9 () / () F 7/ 4() / 8/9 5 7/ (5) 8/9 7/ (5) 8/9 rugi wariant () / () () 7/ () / () / () () / () / () () () () () /4 () / () () /4 () / () () /4 () / () () () () Zofia Kruczkiewicz, USM, Algorytmy i struktury danych, Wykład, 7
Zofia Kruczkiewicz, USM, Algorytmy i struktury danych, Wykład, 8 () /4 () / () () / () /4 () / () () / () /4 () / 4() () () /7 () /4 () / 4() 8/ () () /7 9/ () /4 () / 4() 8/ () () /7 9/ () /4 () / 4() 8/ () (5) /7 9/ () /4 () / 4() 8/ () () /7 () /4 () / 4() 8/ () () /7 9/ () /4 () / 4() 8/ () () /7 9/ () /4 () / 4() 8/ () () /7 9/
Wypisywanie wierzchołków ścieżki z s do v przy założeniu, że drzewa przeszukiwań zostały wcześniej zbudowane za pomocą procedury FS: rukuj (G, s, v). jeśli (v == s) to wypisz (s) lub jeśli (wierzcholki[v].odwiedzony == ) to komunikat ( rak scieżki z s do v ) lub { rukuj(g, s, wierzcholki[v].odwiedzony) wypisz(v) } Złożoność obliczeniowa procedury FS zas inicjowania tablicy (linia procedury) oraz czas wybierania kolejnego wierzchołka (linia procedury) jest równy O(V). Łączny czas odwiedzania listy sąsiedztwa każdego wierzchołka białego jest równy O(E) - czas procedury FS_VISIT, gdzie E jest zbiorem krawędzi grafu i odwiedzane są jedynie białe wierzchołki w liście sąsiedztwa. Każde przeszukanie pojedynczej listy sąsiedztwa jest wykonywane tylko raz dla każdego wierzchołka należącego do zbioru wierzchołków V. Stąd czas działania procedury FS jest równy O(V+E). Uwaga: Inne przykłady rozwiązywane metodą algorytmów z powrotami Problem n królowych (ustawienie takie, aby królowe się nie szachowały), problem sumy podzbiorów (znalezienie wśród zbioru przedmiotów, podzbioru o zadanej wadze W), kolorowanie grafu nieskierowanego (znalezienie wszystkich sposobów pokolorowania wierzchołków przy zastosowaniu co najwyżej m kolorów, aby sąsiednie wierzchołki nie miały tego samego koloru), problem cyklu Hamiltona (wyszukanie w grafie nieskierowanym ścieżki, która rozpoczyna się na wybranym wierzchołku, odwiedza każdy wierzchołek grafu dokładnie jeden raz i kończy się na pierwszym wierzchołku), optymalizacyjny problem plecakowy (przy założonej wadze plecaka maksymalizacja wartości chowanych przedmiotów), Zofia Kruczkiewicz, USM, Algorytmy i struktury danych, Wykład, 9
.. Algorytm przeszukiwania wszerz FS obliczanie najkrótszej ścieżki z s do wszystkich osiągalnych wierzchołków metodą podziału i ograniczeń Jest to usprawnienie algorytmu z powrotami. Nie narzuca on żadnego określonego sposobu przeglądania drzewa oraz jest wykorzystywany jedynie do problemów optymalizacyjnych. Oblicza on w każdym węźle liczbę (granicę), która pozwoli stwierdzić, czy ten węzeł jest obiecujący. Liczba ta jest granicą wartości rozwiązania, jakie może zostać uzyskane dzięki rozwinięciu węzła. Jeśli ta granica nie jest lepsza niż wartość dotychczas znalezionego rozwiązania, węzeł jest nieobiecujący. Wartość optymalna jest albo minimalna albo maksymalna, czyli wartość lepsza oznacza tu albo większą albo mniejszą wartość. W najgorszym wypadku algorytmy te mają złożoność wykładniczą lub gorszą od wykładniczej. G= {V, E}, gdzie V jest zbiorem wierzchołków (węzłów) i E zbiorem krawędzi IALY kolor nadawany nie odwiedzonym wierzchołkom SZARY kolor nadawany odwiedzonym wierzchołkom ZARNY kolor nadawany węzłowi, którego lista sąsiedztwa została odwiedzona wierzcholek { kolor; odwiedzony; czas; } wierzcholek wierzcholki[v[g]] FS (G). dla każdego wierzchołka u należącego do V[G] { wierzcholki[u].kolor = IALY wierzcholki[u].czas = - wierzcholki[u].odwiedzony = }. wierzcholki[s].kolor = SZARY. wierzcholki[s].czas = 4. Inicjuj (Kolejka) 5. Wstaw(Kolejka, s). opóki!pusta(kolejka).. u = Usun(Kolejka) //u nie jest usuwany z kolejki, lecz odczytany z jej początku.. dla każdego wierzcholka v należącego do listy sąsiedztwa wierzchołka u jeśli wierzcholki[v].kolor == IALY to { wierzcholki[v].kolor = SZARY wierzcholki[v].czas = wierzcholki[u].czas + wierzcholki[v].odwiedzony = u Wstaw(Kolejka, v) }.. Usun(Kolejka) //usuwany pierwszy element z kolejki.4. wierzcholki[u].kolor = ZARNY Zofia Kruczkiewicz, USM, Algorytmy i struktury danych, Wykład,
Wypisywanie wierzchołków najkrótszej ścieżki z s do v przy założeniu, że drzewo najkrótszych ścieżek zostało wcześniej zbudowane za pomocą procedury FS: rukuj (G, s, v). jeśli (v == s) to wypisz (s) lub jeśli (wierzcholki[v].odwiedzony == ) to komunikat ( rak scieżki z s do v ) lub { rukuj(g, s, wierzcholki[v].odwiedzony) wypisz(v) } Złożoność obliczeniowa: ) zas operacji na kolejce jest równy O(V). Po każdym przeglądaniu listy sąsiedztwa pojedynczego wierzchołka jest on usuwany z kolejki. Łączny czas przeglądania listy sąsiedztwa każdego wierzchołka jest równe O(E). Inicjowanie trwa O(V). zas procedury FS wynosi O (V + E). ) Procedura rukuj (G, s, v) działa w czasie liniowym, gdyż każde wywołanie rekurencyjne następuje dla ścieżki krótszej o jeden wierzchołek. Uwaga: Inne przykłady rozwiązywane metodą podziału i ograniczeń problem plecakowy (przy założonej wadze plecaka maksymalizacja wartości chowanych przedmiotów) problem komiwojażera (znalezienie najkrótszej ścieżki w grafie skierowanym, rozpoczynającej się w danym wierzchołku, odwiedzającej wszystkie wierzchołki dokładnie raz i kończącej się w wierzchołku początkowym) Zofia Kruczkiewicz, USM, Algorytmy i struktury danych, Wykład,
Zofia Kruczkiewicz, USM, Algorytmy i struktury danych, Wykład, () - () - () - 7() - () - Q () () - () 7() () - Q 7 () () - () 7() () - Q 7 () () - () 7() () - Q 7 () () 4() () 7() () Q 7 4 () () 4() () 7() () Q 7 4 () () 4() () 7() () Q 4 - - - - - - - () () 4() () 7() () Q - () () 4() () 7() () Q 5() 5 () () 4() () 7() () Q 5() 5 () () 4() () 7() () Q 5()
.. Algorytm Floyda określania najkrótszej ścieżki w grafie metodą programowania dynamicznego. Programowanie dynamiczne usuwa niedogodności algorytmów typu dziel i zwyciężaj, które wykonując podziały, mogą powtórzyć rozwiązanie tych samych realizacji i stają się wtedy bardzo niewydajne. Przykład ) Obliczanie liczb Fibonacciego rzędu w sortowaniu polifazowym z trzema plikami metodą programowania dynamicznego Serie w plikach Idealne serie Numer poziomu Liczba f f f f f scalania - l serii 8 8 5 8 8 5 5 5 5 4 8 5 f =, l+ l f =, f f =, f f f l l l + = + dla l > int Fibonacci (int n) { int i, f[n+]; f[]=; if (n > ) f[] = ; for (i = ; i<=n; i++) { f[i] = f[i -] + f[i ]; } return f[n]; } l Jeśli przyjmie się, że f = f l, to wzory rekurencyjne definiujące ciąg Fibonacciego rzędu : f = f + f dla i = = + oraz f, f i i i Wniosek: Początkowe liczby serii na dwóch plikach muszą być dwoma kolejnymi elementami ciągu Fibonacciego rzędu, natomiast trzeci plik służy do łączenia serii na kolejnym poziomie. ) Obliczanie liczb Fibonacciego metodą dziel i zwyciężaj int Fibonacci(int n) { if (n <= ) return n; else return Fibonacci (n-) + Fibonacci (n-) } Aby obliczyć liczby Fibonacciego n i n+ należy dwukrotnie obliczyć liczbę n- itd. Prowadzi to do złożoności wykładniczej n/ n Prog. yn. Algorytm ziel i zwyciężaj - dolne ograniczenie czasu 8 8 ns.* ns = 8 min ns.* ns = 4 * lat Zofia Kruczkiewicz, USM, Algorytmy i struktury danych, Wykład,
Programowanie dynamiczne polega na wykonaniu następujących działań: ) Określa się właściwość rekurencyjną, która pozwala znaleźć rozwiązanie realizacji problemu ) Rozwiązuje się realizację problemu zgodnie z podejściem wstępującym, najpierw rozwiązując mniejsze realizacje Algorytm Floyda wyznaczania najkrótszej ścieżki w grafie Θ(N ) Zadanie: Należy obliczyć najkrótsze drogi z każdego wierzchołka w grafie ważonym do wszystkich innych wierzchołków. Wagi krawędzi są liczbami nieujemnymi. ana jest macierz sąsiedztwa Graf o rozmiarze N x N, której elementy Graf[i][j] są wagą krawędzi prowadzącej od i-tego wierzchołka do j-tego wierzchołka lub równe dla i=j oraz równe N (N oznacza nieskończoność), gdy brak krawędzi. W wyniku algorytmu otrzymuje się tablicę dwuwymiarową o rozmiarze N x N, gdzie [i][j] jest długością najkrótszej drogi prowadzącej z i-tego wierzchołka do j-tego wierzchołka oraz tablica dwuwymiarowa P o rozmiarze N x N, gdzie P[i][j] jest numerem pośredniego wierzchołka o najwyższym indeksie w najkrótszej drodze od i-tego wierzchołka do j-tego wierzchołka lub -, jeśli taki wierzchołek nie istnieje. void Floyd (int N, const int Graf [ ][N], int [ ][N], int P[ ][N]) { int i, j, k for (i = ; i<n; i++) for (j =; j<n; j++) P[i][j] = -; memmove(, Graf,N*N*sizeof(int)); for (k = ; k<n; k++) for (i = ; i< N; i++) for (j=; j<n; j++) if ([i][k] +[k][j] < [i][j]) { P[i][j] = k; [i][j]= [i][k] + [k][j]; } } 5 Wagi krawędzi są równe, N= 4 Graf 4 5 4 5 4 5 4 4 4 5 P 4 5 - - 5 - - - 5 - - - - 5 - - - - 5-4 5 5 5 5 - - 5 5 - - - - - - - 5 - - Zofia Kruczkiewicz, USM, Algorytmy i struktury danych, Wykład, 4
void drukuj(int P[ ][N], int s, int v) { if (P [s][v]!=-) { drukuj(p, s, P[s][v]); cout<<"v: "<< P[s][v]; drukuj(p, P[s][v], v); } } Zofia Kruczkiewicz, USM, Algorytmy i struktury danych, Wykład, 5