Algorytmy i struktury danych
Transkrypt
Algorytmy i struktury danych
Algorytmy i struktury danych ĆWICZENIE 2 - WYBRANE ZŁOŻONE STRUKTURY DANYCH - (12.03.2012) Prowadząca: dr hab. inż. Małgorzata Sterna Informatyka i3, poniedziałek godz. 11:45 Adam Matuszewski, nr 106550 Oliver Kostera , nr 106552 1.Tworzenie struktury danych Czas (w sekundach) tworzenia struktury 2 1,8 1,6 Czas [s] 1,4 1,2 1 cB 0,8 cL 0,6 cTR 0,4 cTB 0,2 0 Liczba elementów Rozmiar 50000 100000 200000 300000 400000 500000 600000 700000 800000 900000 1000000 1500000 cL 0,01 0,01 0,01 0,03 0,02 0,04 0,04 0,06 0,06 0,09 0,08 0,14 cTB 0,01 0,03 0,05 0,08 0,11 0,12 0,16 0,18 0,22 0,25 0,28 0,42 cB 0,01 0,03 0,07 0,11 0,15 0,19 0,23 0,28 0,32 0,36 0,4 0,62 cTR 0,02 0,05 0,16 0,28 0,41 0,54 0,7 0,81 1,06 1,09 1,39 1,78 Najszybciej powstaje lista jednokierunkowa, zdecydowanie najwolniej jako drzewo poszukiwań binarnych TR. Podczas budowy drzewa następuje wiele porównań przez co ma złożoność O(n*log2n). Tworzenie listy ma złożoność O(n). Tworzenie drzewa TR trwa dłużej niż tworzenie drzewa TB, ponieważ drzewo TR jest wyższe(oprócz wypadku optymistycznego – wtedy jest takie same), a zatem znalezienie miejsc, w które należy wstawić kolejne elementy wymaga większej liczby porównań. 2. Wyszukiwanie w strukturach danych Czas wyszukiwania wszystkich elementów w standardowej tablicy i na liście: 12000 10000 Czas [s] 8000 6000 ssB 4000 sL 2000 0 Liczba elementów Czas (w sekundach) wyszukiwania wszystkich elementów w tablicy połówkowej i drzewach: 2 1,8 1,6 1,4 Czas [s] 1,2 1 sbB 0,8 sTR 0,6 sTB 0,4 0,2 0 Liczba elementów Rozmiar sTB sTR sbB ssB sL 50000 100000 200000 300000 400000 500000 600000 700000 800000 900000 1000000 0,01 0,03 0,09 0,16 0,23 0,3 0,39 0,46 0,56 0,63 0,74 0,02 0,04 0,14 0,25 0,38 0,5 0,65 0,81 1,01 1,09 1,31 0,02 0,03 0,09 0,16 0,26 0,37 0,55 0,63 0,77 0,97 1,15 8,03 31,98 128,22 290,2 516,92 809,01 1166,45 1588,35 2075,25 2626,33 3243,45 8,99 42,67 189,27 453,72 812,98 1312,12 2015,37 2892,59 3845,18 4648,45 6095,72 1500000 0,99 1,78 1,9 7298,27 11127,9 Algorytmy wyszukiwania elementu w tablicy i w liście działają na bardzo podobnej zasadzie, porównują kolejne elementy z wartością szukaną, dopóki jej nie znajdą, przez co czas działania wydłuża się. Wyszukiwanie w tablicy okazało się jednak szybsze, być może dlatego że bezpośrednie odwołanie do elementu może zajmować mniej czasu niż odwołanie poprzez poprzedni element na liście. Algorytmy wyszukiwania połówkowego w tablicy i wyszukiwania w drzewie TB również działają na podobnej zasadzie - korzystamy z uporządkowania elementów w strukturze tzn. jeśli bieżący element jest większy(mniejszy) od szukanego elementu, kontynuujemy szukanie tylko dla elementów mniejszych(większych) od bieżącego. Pozwala to na zmniejszenie złożoności do O(n*log2n). Wyszukiwanie połówkowe w tablicy przebiega jednak wolniej, gdyż wymaga każdorazowego wyliczania indeksu, pod którym znajdziemy kolejny porównywany element, podczas gdy węzły drzewa zawierają do niego bezpośredni wskaźnik. Czas [s] 3. Wysokość drzew poszukiwań binarnych 500 450 400 350 300 250 200 150 100 50 0 hTB hTR Liczba elementów Rozmiar 50000 100000 200000 300000 400000 500000 600000 700000 800000 900000 1000000 1500000 hTB 16 17 18 19 19 19 20 20 20 20 20 21 hTR 111 101 128 139 265 195 283 144 380 255 434 413 Wysokość drzewa TR jest znacznie większa niż wysokość drzewa TB. Wprowadzenie danych w kolejności wynikającej z dzielenia połówkowego tablicy posortowanej umożliwia nam stworzenie drzewa o wysokości 1+log2n, czyli drzewa wyważonego (TB). Gdybyśmy umieszczali posortowane dane wg tablicy B to drzewo składałoby się z jednej długiej gałęzi. Wysokość takiego drzewa byłaby równa n. W przypadku drzewa TR dane wprowadzane są losowo a jego wysokość zawiera się w przedziale od 1+log2n do n. Wysokość jest zależna od danych. Wysokość drzewa poszukiwań binarnych jest bardzo istotna, gdyż reguluje czas wykonywania podstawowych operacji na tej strukturze, takich jak wyszukiwanie bądź dodawanie nowego elementu. Aby np. odszukać w drzewie konkretny element musimy bowiem przejść całą ścieżkę od korzenia, aż do tego elementu, wykonując przy tym tyle porównań ile wynosi długość ścieżki. Wysokość drzewa będzie więc oznaczała maksymalną liczbę porównań które musimy wykonać żeby znaleźć szukany element. Im niższe drzewo tym mniej porównań, krótszy czas wykonywania operacji i korzystniejsza struktura. 4.Wady i zalety Złożoność pamięciowa wszystkich struktur jest taka sama i jest O(n). Jednak elementy tablicy zawierają jedynie wartość danej, element listy zawiera dane i wskaźnik, zaś element drzewa dane oraz dwa wskaźniki. Tablice: + bezpośredni dostęp do elementów + łatwa implementacja – gotowa struktura + szybkie tworzenie (złożoność O(n), wydłuża się dla tablicy posortowanej) + krótki czas wyszukiwania na zasadzie dzielenia połówkowego (wymaga posortowania) + najmniejsze wymagania pamięciowe - najdłuższy czas wyszukiwania elementu (dla prostego wyszukiwania, złożoność O(n)) - niewielka elastyczność (trudno dodać bądź usunąć element, zmienić rozmiar tablicy itp.) Lista jednokierunkowa: + wysoka elastyczność (łatwe dodawanie i usuwanie elementów, zmienianie rozmiaru listy itp.) + łatwa implementacja – lecz brak gotowej struktury + najkrótszy czas tworzenia (złożoność O(n)) - długi czas wyszukiwania elementu (złożoność O(n)) - nienaturalny dostęp do elementów - niełatwe sortowanie Drzewa BST: + logarytmiczna złożoność wyszukiwania elementu (w przypadku pesymistycznym degraduje się do O(n)) - średnia elastyczność (dodanie elementu wymaga wielu operacji porównania, usunięcie też może być skomplikowane) - nienaturalny dostęp do elementów - najtrudniejsza implementacja(lecz nadal dość łatwa) - dłuższy czas tworzenia (szczególnie dla posortowanych danych, złożoność od O(n*log2n) do nawet O(n2)) - duża zależność złożoności operacji od danych wejściowych - największe wymagania pamięciowe