Wypracowanie algo kompletne

Uniwersytet Śląski

Wydział Informatyki i Nauki o Materiałach

Paweł Grzesica

Nr albumu: 251956

Analiza i złożoność obliczeniowa algorytmów

Wyszukiwanie binarne(połówkowe) oraz drzewa poszukiwań binarnych (BST)

Sosnowiec, 2013

Spis treści

Wstęp ………………………………………………………………………………………… 2

1. Pojęcie wyszukiwania ……………………………………………………………………. 3

2. Wyszukiwanie binarne …………………………………………………………………... 3

2.1. Pojęcie i algorytmy wyszukiwania binarnego ………………………………… 3

2.2. Złożoności obliczeniowe ………………………………………………………... 4

2.3. Schemat blokowy ……………………………………………………………….. 6

3. Drzewa przeszukiwań binarnych ……………………………………………………….. 7

3.1. Pojęcie i algorytmy drzew poszukiwań binarnych …………………………… 7

3.2. Złożoności obliczeniowe ………………………………………………………... 8

3.3. Drzewa AVL ……………………………………………………………………. 9

Zakończenie ………………………………………………………………………………... 11

Wstęp

Przeszukiwanie algorytmów w dużej mierze zależy od posiadanego zbioru danych i jego ustrukturyzowana. Świadomość tego pozwala na wybór najlepszego i najszybszego w danej chwili narzędzia. Praca ma na celu zaprezentowanie dwóch metod przeszukiwania posortowanych danych, ich wad oraz zalet.

Praca składa się z trzech części teoretycznych, poprzedzonych wstępem. W pierwszej części została omówiona definicja wyszukiwania oraz jego rodzaje. W drugiej części zaprezentowano wyszukiwanie binarne, algorytm i jego schemat, złożoności obliczeniowe oraz jego wady i zalety. W trzeciej części skupiono się na drzewach wyszukiwań binarnych, ich własnościach i złożoności oraz na specyficznym rodzaju drzew binarnych, jakim jest drzewo AVL.

W pracy wykorzystano analizę literatury zwartej oraz artykuły specjalistyczne udostępnione za pośrednictwem internetowych serwisów w kraju, a także analizę danych dotyczących wyszukiwania binarnego i drzew BST na stronach w sieci Internet. Najbardziej pomocne okazały się źródła internetowe, dostarczając najwięcej danych na temat problematyki pracy.

1. Pojęcie wyszukiwania

Algorytm jest ciągiem kroków obliczeniowych, mającym na celu przekształcenie danych wejściowych w wyjściowe. Jest on więc rozwiązaniem konkretnego problemu obliczeniowego. W zależności od potrzeb istnieją różne typy algorytmów, jak algorytm sortowania, selekcji, wstawiania, usuwania etc.

Algorytm wyszukiwania jest jednym z najczęściej stosowanych. Wyszukiwanie jest sposobem, za pomocą którego przeszukuje się zbiór danych (najczęściej w postaci tablicy) w celu znalezienia wymaganych zmiennych.

Istnieje wiele algorytmów wyszukiwania :

Uwaga w niniejszej pracy zostanie poświęcona wyszukiwaniu binarnemu (połówkowemu) oraz drzewom przeszukiwań binarnych (BST). Oba wyszukiwania oparte są na metodzie „dziel i zwyciężaj” (rekurencja opierająca się na podziale jednego poziomu rekursji na trzy etapy).

2. Wyszukiwanie binarne

2.1. Pojęcie i algorytmy wyszukiwania binarnego

Szukanie binarne, zwane również połówkowym, jest szybką metodą wyszukiwania elementów w czasie logarytmicznym w posortowanych tablicach, skąd bierze swoją nazwę. W przypadku znalezienia szukanej podaje jej indeks w tablicy. Sortowanie może być dowolne, w zależności od wymagań: rosnące, malejące etc.

Rozpoczęcie przeszukiwania tablic rozpoczyna się w momencie dzielenia na coraz mniejsze podtablice. Algorytm rozpoczyna swoje działanie od przeszukania całej tablicy. W pojedynczym kroku wyszukuje się indeksy początkowy i końcowy. Po wyznaczeniu środka przedziału tych indeksów, sprawdzana jest jego poprawność – gdy indeks środkowy jest poszukiwanym, algorytm kończy działanie. W przeciwnym wypadku algorytm sprawdza położenie poszukiwanej wartości i, w zależności od tego, czy znajduje się ona bliżej początku (lewej części badanej tablicy) czy końca indeksu (prawej strony badanej tablicy), procedura jest powtarzana od nowa.

Przykładowy algorytm wyszukiwania binarnego:

procedure wyszukiwanie binarne(x: typ klucza;

var jest: Boolean ;

var m: 1 .. n);

var lewy, prawy: 0 .. n + 1;

begin

lewy := 1; prawy := n; jest := false ; repeat

m := (lewy + prawy) div 2;

if A[m].klucz = x then

jest := true ;

else

if A[m].klucz < x then

lewy := m + 1;

else

prawy := m − 1;

end if;

end if;

until jest or (lewy > prawy);

end; {wyszukiwanie binarne}

2.2. Złożoności obliczeniowe

Złożoność obliczeniowa pozwala oszacować czas potrzebny do wykonania algorytmu. Złożoność tę wyznacza zależność czasu potrzebnego do wykonania algorytmu od rozmiaru danych wejściowych (najczęściej jest to ich ilość). Na złożoność obliczeniową algorytmu składa się złożoność czasowa i złożoność pamięciowa. W przypadku algorytmów można wyróżnić kilka rodzajów złożoności matematycznych:

Złożoność czasowa jest zależnością pomiędzy liczbą operacji elementarnych wykonywanych w trakcie przebiegu algorytmu, a rozmiarem danych wejściowych. Wynika z liczby operacji elementarnych wykonywanych w trakcie przebiegu algorytmu i decyduje o tym, czy dany algorytm jest przydatny. O złożoności czasowej decyduje liczba wykonywanych iteracji

Całkowity koszt czasowy wynosi

T(N) = K1 + max( K3,K4) + K2 * lg N

W przypadku wyszukiwania binarnego złożoność obliczeniowa czasowa jest logarytmiczna i wynosi

T(N) = O (log n),

co oznacza, że czas potrzebny na wyszukanie elementu tą metodą rośnie w sposób logarytmiczny wraz z liniowym wzrostem liczby elementów w przeszukiwanej tablicy. Zapis T(N) = O(f(n)) oznacza, że istnieją takie stałe dodatnie c oraz n0, że dla każdego n ≥ n0 zachodzi T(N) ≤ cf(n) TW(n) ≤ TA(n). Algorytm ten jest więc bardzo szybki. Logarytmiczna złożoność jest osiągana dzięki temu, że każde wykonane porównanie zmniejsza o połowę przedział, w którym może znajdować się szukana wartość.

Złożoność pamięciowa jest to cecha algorytmu, która wynika z liczby i rozmiaru struktur danych wykorzystywanych w algorytmie. Złożoność ta wyznacza zależność rozmiaru pamięci potrzebnej do realizacji algorytmu od wielkości danych wejściowych. Ten sam algorytm uruchomiony jako program na komputerach o różnych konfiguracjach może wymagać różnej wielkości pamięci. Złożoność pamięciowa jest najczęściej proporcjonalna do liczby zmiennych użytych w algorytmie. Określa ona więc ilość pamięci, którą potrzebuje algorytm na rozwiązanie problemu. Dla wyszukiwania binarnego złożoność pamięciowa wynosi O (1). Oznacza to, że algorytm zużywa stałą liczbę komórek pamięci bez względu na rozmiar danych n. Czas wykonania jest stały i nie zmienia się przy zmianie liczby przetwarzania elementów.

Rozróżnia się dwa rodzaje czasowej i pesymistycznej złożoności obliczeniowej:

TW(n) = sup {t(d): d ∈ Dn}, gdzie sup oznacza kres górny zbioru. W najgorszym wypadku iteracja w algorytmie jest powtarzana 1+ log2 N (= log N). Zatem pesymistyczna złożoność algorytmu wyszukiwania binarnego wynosi:

TW (n)log n+1,

TŚR ≈ log n -1.

2.3. Schemat blokowy

Schemat blokowy jest jednym ze sposobów opisu algorytmu i zawiera plan algorytmu przedstawiony w postaci graficznej struktury elementów zwanymi blokami. Każdy blok zawiera informację o operacji, która ma być w nim wykonana, a pomiędzy blokami umieszczone są linie przepływu (strzałki) określające kolejność wykonywania bloków algorytmu.


3. Drzewa przeszukiwań binarnych

3.1. Pojęcie i algorytmy drzew poszukiwań binarnych

Drzewa binarne są rodzajem struktury danych, w których liczba synów w każdym wierzchołku nie przekracza dwóch. Drzewa binarne zawierające w wierzchołku zero lub dwóch synów noszą nazwę drzew regularnych. Drzewa ułatwiają i przyspieszają wyszukiwanie, a także pozwalają w łatwy sposób operować na posortowanych danych. Znaczenie tych struktur jest bardzo duże i ze względu na swoje własności drzewa są stosowane praktycznie w każdej dziedzinie informatyki (np. bazy danych, grafika komputerowa, przetwarzanie tekstu, telekomunikacja). Szczególną odmianą drzew binarnych są drzewa przeszukiwań binarnych.

Drzewa przeszukiwań (poszukiwań) binarnych, w skrócie BST (z ang. binary search trees), są dowolnymi drzewami binarnymi, w których elementy zbioru są wpisanego wierzchołków zgodnie z porządkiem symetrycznym. Są więc dynamicznymi strukturami, zbudowanymi z węzłów: każdy węzeł może posiadać dwóch potomków oraz jednego przodka, ponadto z każdym węzłem związany jest klucz. Dla każdego węzła (nie będącego liściem) wszystkie wartości przechowywane w lewym poddrzewie są mniejsze od wartości tego węzła, natomiast wszystkie wartości przechowywane w prawym poddrzewie są większe od wartości w tym węźle. Wysokość drzewa zależy od kolejności danych. Drzewo BST można zrealizować za pomocą struktury danych z dowiązaniami (np. listy), w której każdy węzeł jest obiektem. Jeżeli węzeł nie ma następnika albo poprzednika, to odpowiednie pole ma wartość NIL (=null).

Drzewa te są zarówno słownikiem jak i kolejką priorytetową. Można na nich wykonywać różne operacje właściwe dla zbiorów dynamicznych, jak:

Algorytm drzewa przeszukiwań binarnych:

type

wierzchołek drzewa = record

klucz: typ klucza;

lewy, prawy: ˆwierzchołek drzewa;

end;

odsyłacz =ˆwierzchołek drzewa;

procedure szukaj (x: klucz ; var t: odsyłacz);

{Szukanie klucza x w drzewie wskazanym przez t.}

var v: odsyłacz ;

begin

v := t ;

while (v = nil) cand (vˆ.klucz = x) do

if x < vˆ.klucz then

v := vˆ.lewy;

else

v := vˆ.prawy;

end if;

end while;

return(v); {jeśli v = nil to x nie występuje w drzewie}

end; {szukaj}

procedure wstaw (x: klucz ; var t: odsyłacz);

{Wstawianie klucza x do drzewa wskazanego przez t.}

var v: odsyłacz ;

begin

v := t ;

while (v = nil) cand (vˆ.klucz = x) do {szukania klucza x}

if x < vˆ.klucz then

v := vˆ.lewy;

else

v := vˆ.prawy;

end if;

end while;

if v = nil then {x jest w drzewie}

13

return;

else

Wstawienie x na koniec ścieżki;

end if;

end; {wstaw}

procedure usuń (x: klucz ; var t: odsyłacz);

{Usuwanie klucza x z drzewa wskazanego przez t.}

var v, w: odsyłacz ;

begin

v := t ;

while (v = nil) cand (vˆ.klucz = x) do {szukania klucza x}

if x < vˆ.klucz then

v := vˆ.lewy;

else

v := vˆ.prawy;

end if;

end while;

if v = nil then {x nie występuje w drzewie}

return;

else

if (vˆ.lewy = nil) or (vˆ.prawy = nil) then {brak lewego lub prawego poddrzewa}

Usuń wierzchołek vˆ z drzewa;

else

w := vˆ.prawy;

while wˆ nie jest końcem ścieżki w drzewie do

w := wˆ.lewy; {szukanie minimalnego elementu w prawym poddrzewie}

end while;

Wstaw wˆ.klucz do vˆ.klucz i usuń wierzchołek wˆ z drzewa;

end if;

end if;

end {usuń}

3.2. Złożoności obliczeniowe

Do reprezentacji drzew BST można wykorzystać różne struktury tworzone w oparciu o zmienne dynamiczne. Podstawowe operacje na drzewach poszukiwań binarnych wymagają czasu proporcjonalnego do wysokości drzewa– o czasie operacji wykonywanych na drzewach decyduje ich wysokość.

Aby obliczyć oczekiwaną złożoność czasową należy oznaczyć przez G(n) oczekiwaną sumę głębokości wierzchołków zewnętrznych w BST, utworzonym z drzewa pustego. Ponieważ lewe i prawe poddrzewa od korzenia drzewa losowego BST są losowe mamy


$$\left\{ \begin{matrix} G\left( 0 \right) = 0\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \\ G\left( n \right) = \left( n + 1 \right) + \frac{1}{n\ }\sum_{j = 1}^{n}\left( G\left( j - 1 \right) + G\left( n - j \right) \right) \\ \end{matrix} \right.\ $$

Rozwiązanie równania jest więc:

TA(n) = $\ \frac{G(n)}{(n + 1)}$ = 1,4 log n + O(1)

Tyle samo wynosi oczekiwana złożoność czasowa operacji search w przypadku, gdy element znajdzie się w drzewie.

W pełnym (tzw. zrównoważonym) drzewie binarnym o n węzłach elementarne operacje takie wyszukiwania, wstawianie węzła czy jego usuwanie działają w pesymistycznym czasie O(n), gdzie n jest wysokością drzewa (przechodzi się po ścieżce w dół drzewa). Notacja ta ogranicza funkcję T(n) od góry. W literaturze często też podaje się koszt ten w uzależnieniu od wysokości drzewa h - wynosi on O(h).

Czas działania poszczególnych procedur w drzewach BST:

Operacje Średnia zł. obl. Pesymistyczna zł. obl.
Space O (n) O (n)
Search O (log n) O (n)
Insert O (log n) O (n)
Delete O (log n) O (n)

Źródło: opracowanie własne na podst. L. Bałachowski, K. Diks, W. Rytter, Algorytmu i struktury danych, WNT Warszawa 1996, 2001, str. 100- 112.

Przykładowy schemat drzewa BST:

3.3. Drzewa AVL

Wraz ze wzrostem wartości h wysokości drzewa BST w stosunku do całkowitej liczby jego wierzchołków, opłacalność stosowania klasycznych drzew wyszukiwań binarnych stopniowo maleje – w skrajnym przypadku takie drzewo jest tyle samo warte, co zwykła lista.  Drzewa BST mogą degenerować się do list liniowych, co powoduje wzrost klasy złożoności obliczeniowej dla operacji wstawiania, usuwania oraz wyszukiwania do O(n). Aby uniknąć degeneracji (przez które zanikają zalety drzew BST), stworzono wiele różnych odmian drzew BST. Jedną z prostszych z nich są drzewa AVL.

Drzewo AVL, jest drzewem BST, w którym poddrzewa każdego węzła różnią się wysokością (ilością poziomów) co najwyżej o 1 – gwarantuje to zrównoważenie drzewa AVL. Mają na celu gwarantowanie wysokości czasu działania na poziomie O (log n)
(n – liczba wierzchołków) podczas operacji serach, insert i delete.

Współczynniki równowagi w drzewie AVL mogą się zmienić tylko w przypadku, gdy zmianie ulega wysokość jakiegoś poddrzewa jednego z węzłów. Z kolei do sytuacji tej może dojść tylko przy wstawianiu nowego węzła lub przy usuwaniu węzła. Pozostałe operacje nie zmieniają wysokości poddrzew, mogą więc być identyczne jak w zwykłym drzewie BST.

Jeśli losowo zbudowane drzewo BST ma co najwyżej n węzłów, to prawdopodobieństwo, że dowolny węzeł ma głębokość co najmniej 2(β + 1)Hn , wynosi co najwyżej n(2/n2) = 2/n. Stąd wynika, że z prawdopodobieństwem co najmniej 1-2/n wysokość losowo zbudowanego drzewa BST jest mniejsza niż 2(β + 1)Hn, a z prawdopodobieństwem co najwyżej 2/n wynosi co najmniej (2β + 1)H, ale nie więcej niż n. Jej wartość oczekiwana jest więc nie większa niż (2(β + 1)Hn) ($\frac{1 - 2}{n}$)+n($\frac{2}{n}$) = O(lg n).


Zakończenie

Sposobów na przeszukiwanie algorytmów jest wiele i tak naprawdę wybór odpowiedniego zależy od struktury i usystematyzowania algorytmu. Ułatwieniem dla użytkownika jest z pewnością uporządkowanie algorytmu, gdyż łatwiej wybierać metodę.

Wyszukiwanie binarne jest metodą nie tylko szybką. Algorytm zużywa stałą liczbę komórek pamięci, co oznacza, że czas wykonania jest stały i nie zmienia się przy zmianie liczby przetwarzania elementów.

Z kolei drzewa BST są bardzo wygodną strukturą do poszukiwań danych: stosując je można w krótkim czasie wykonać operacje szukania, dodawania i usuwania elementów w zbiorze. Operacje te posiadają dla drzew BST złożoność obliczeniową klasy O(log n), jeśli drzewo BST jest zrównoważone.  Działają one tym szybciej, im mniejszą wysokość posiada drzewo BST.

Bibliografia:

1. Bałachowski L., Diks K., Rytter W., „Algorytmy i Struktury Danych”, WNT, Warszawa 1996.

2. Carmen T.H., Leiserson C.E., Rivest R.L., Stein C., „Wprowadzenie do algorytmów“, WNT, Warszawa 1997,2001.

3. Czech Z.J., „Algorytmy i struktury danych, materiały dydaktyczne”

4. www.cs.put.poznan.pl

5. www.edu.i-lo.tarnow.pl

6. www.iair.mchtr.pw.edu.pl

7. www.oxygene.ibspan.waw.pl

8. www.we.pb.edu.pl


Wyszukiwarka

Podobne podstrony:
Wypracowanie algo
Wypracowanie algo
KOMPLEKSY POLAKOW wykl 29 03 2012
pytania nowe komplet
zwiazki kompleksowe 2
8 kompleksy
W19 kompleksonometria, wska«niki i krzywe miareczkowania kompleks i
Bliskowschodni kompleks bezpieczeństwa Przyczyny destabilizacji w regionie
Kompleksowa ocena geriatryczna
statyst wyprac, Testowanie
Komplementarnosc
Kompleksowa rozgrzewka z pilkam Nieznany
Kompleksowa rozgrzewka z pilkam Nieznany (2)
ModulIII cz3 kompleksy i osady Nieznany
Metody kompleksowego zarządzania jakością karty kontrolne
dok po wypadku komplet, polec pow
Historia arkusz IIIb (czasy nowozytne do roku 1915) poziom rozszerzony wypracowanie6

więcej podobnych podstron