• Nie Znaleziono Wyników

Algorytmy 2 Laboratorium: kopiec binarny

N/A
N/A
Protected

Academic year: 2021

Share "Algorytmy 2 Laboratorium: kopiec binarny"

Copied!
4
0
0

Pełen tekst

(1)

Algorytmy 2

Laboratorium: kopiec binarny

Przemysław Klęsk 30 września 2019

1 Cel

Celem zadania jest wykonanie implementacji struktury danych nazywanej kopcem binarnym (ang. binary heap). Kopiec binarny zorientowany na maksimum jest drzewem binarnym, w którym każdy węzeł ma klucz większy lub równy kluczom dzieci1. Typowa implementacja kopca jest oparta na tablicy dynamicz- nej, do której węzły drzewa binarnego reprezentującgo kopiec są wpisane kolejno poziomami (wszystkie poziomy kopca poza ostatnim muszą być pełne). Dzięki powyższym warunkom proste operacje arytme- tyczne pozwalają określić indeks rodzica dowolnego węzła oraz indeksy jego dzieci. Przy numerowaniu od zera, rodzic węzła i znajduje się pod numerem ⌊(i − 1)/2⌋, a dzieci pod numerami 2i + 1, 2i + 2. Dwa po- pularne zastosowania kopca to: sortowanie przez kopcowanie (ang. heap sort) i znajdowanie najkrótszych ścieżek (np. algorytmy Dijkstry i A).

W ramach niniejszego zadania badane będą czasy wykonywania dwóch najistotniejszych operacji na kopcu tj.: dodawania nowego elementu oraz pobierania elementu maksymalnego (wraz z usunięciem go)

— tzw. operacja poll. Obie te operacje mają złożoność obliczeniową O(log n), ponieważ naprawianie kopca wymaga pracy proporcjonalnej co najwyżej do jego wysokości. Tym samym wykonywanie tych operacji dla n elementów prowadzi do czasu rzędu O(n log n).

Uwaga: sortowanie na kopcu nie będzie realizowane w ramach tego zadania. Dodatkowe funkcje (me- tody) potrzebne do tego celu pojawią się w ramach późniejszego zadania porównującego sortowanie przez kopcowanie z sortowaniem przez zliczanie (ang. counting sort) i sortowaniem kubełkowym (ang. bucket sort) — czyli tzw. sortowaniami pseudoliniowymi.

2 Instrukcje, wskazówki, podpowiedzi

1. Podobnie jak w poprzednich zadaniach dozwolone są implementacja strukturalna lub obiektowa, przy czym ponownie wymagane jest użycie mechanizmu szablonów (template) języka C++ dla zachowania ogólności.

1W kopcu zorientowanym na minimum: klucz rodzica 6 klucze dzieci.

1

(2)

2. Implementacja może wykorzystywać wcześniej wykonany własny kontener tablicy dynamicznej (np. poprzez dołączenie odpowiedniego pliku nagłówkowego .h i umieszczenie wewnątrz struktury / klasy kopca pola typu tablica dynamiczna). Przy czym nie jest to bezwzględny wymóg.

3. Na potrzeby tego zadania interfejs kopca binarnego powinien udostępniać następujące funkcje / metody:

(a) dodanie nowego elementu (argumenty: dane i informacja lub komparator definiujące klucz porządkowania),

(b) pobranie i usunięcie elementu maksymalnego tj. korzenia kopca (argument: informacja lub komparator definiujące klucz porządkowania — potrzebne do naprawienia kopca po usunięciu korzenia; wynik: dane związane z elementem maksymalnym lub niepowodzenie w razie pustego kopca),

(c) czyszczenie kopca tj. usunięcie wszystkich elementów,

(d) zwrócenie napisowej reprezentacji kopca — np. funkcja / metoda to string(...) (argumen- ty i format wyniku wg uznania programisty — można wykorzystać m.in. napis pochodzący z tablicy dynamicznej, którą kopiec opakowuje),

(e) przekopcowanie rekurencyjne w górę poczynając od podanego indeksu (argumenty: indeks oraz informacja lub komparator definiujące klucz porządkowania),

(f) przekopcowanie rekurencyjne w dół poczynając od podanego indeksu (argumenty: indeks oraz informacja lub komparator definiujące klucz porządkowania).

Punkty (e), (f) reprezentują narzędziowe funkcje naprawcze (na użytek wewnętrzny kopca) — nie powinny być one używane bezpośrednio przez użytkownia zaś wywoływane jedynie z wnętrza po- zostałych funkcji.

4. W programie można wykorzystać ogólne wskazówki z poprzednich zadań dotyczące:

- dynamicznego zarządania pamięcią (new, delete) — w szczególności przemyślenia miejsc od- powiedzialnych za uwalnianie pamięci danych,

- wydzielenia implementacji interfejsu kopca do odrębnego pliku .h, - pracy z napisami (użycie typu std::string),

- pomiaru czasu (funkcja clock() po dołączeniu #include <time.h>), - użycia wskaźników na funkcje,

- generowania losowych danych (funkcje rand() i srand(...)).

3 Zawartość funkcji main()

Główny eksperyment zawarty w funkcji main() ma polegać na wielokrotnym dodawaniu coraz większej liczby elementów (danych) do kopca (rzędy wielkości od 101 aż do 107), a następnie pobieraniu (wraz z

2

(3)

usuwaniem) elementu maksymalnego w kopcu, aż do opróżnienia kopca. Należy raportować czasy doda- wania i pobierania (całkowite i średnie).

Poniższy listing pokazuje schemat eksperymentu (proszę traktować go jako poglądowy przykład):

int main () {

...

const int M A X _ O R D E R = 7; // m a k s y m a l n y rzad w i e l k o s c i d o d a w a n y c h d a n y c h

binary_heap < s o m e _ o b j e c t * >* bh = new binary_heap < s o m e _ o b j e c t * >() ; for ( int o = 1; o <= M A X _ O R D E R ; o ++)

{

const int n = pow (10 , o ) ; // r o z m i a r d a n y c h

// d o d a w a n i e do k o p c a c l o c k _ t t1 = clock () ;

for ( int i = 0; i < n ; i ++) {

s o m e _ o b j e c t * so = ... // l o s o w e dane bh - > add ( so , s o m e _ o b j e c t s _ c m p ) ; }

c l o c k _ t t2 = clock () ;

... // w y p i s na e k r a n a k t u a l n e j p o s t a c i k o p c a ( s k r o t o w e j ) oraz p o m i a r o w c z a s o w y c h

// p o b i e r a n i e ( i u s u w a n i e ) e l e m e n t u m a k s y m a l n e g o z k o p c a t1 = clock () ;

for ( int i = 0; i < n ; i ++) {

s o m e _ o b j e c t * polled = bh - > poll ( s o m e _ o b j e c t s _ c m p ) ; // a r g u m e n t: w s k a z n i k na k o m p a r a t o r ... // e w e n t u a l n y w y p i s na e k r a n d a n y c h e l e m e n t u p o b r a n e g o ( przy m a l y m e k s p e r y m e n c i e ) delete polled ;

}

t2 = clock () ;

... // w y p i s na e k r a n a k t u a l n e j p o s t a c i k o p c a ( k o p i e c p u s t y ) oraz p o m i a r o w c z a s o w y c h

bh - > clear () ; // c z y s z c z e n i e k o p c a ( tak n a p r a w d e ,, z r e s e t o w a n i e ’’ t a b l i c y d y n a m i c z n e j o p a k o w a n e j p r z e z k o p i e c )

}

delete bh ; return 0;

}

4 Sprawdzenie antyplagiatowe — przygotowanie wiadomości e-mail do wysłania

1. Kod źródłowy programu po sprawdzeniu przez prowadzącego zajęcia laboratoryjne musi zostać przesłany na adres algo2@zut.edu.pl.

2. Plik z kodem źródłowym musi mieć nazwę wg schematu: nr albumu.algo2.nr lab.main.c (plik może mieć rozszerzenie .c lub .cpp). Przykład: 123456.algo2.lab06.main.c (szóste zadanie laboratoryjne studenta o numerze albumu 123456). Jeżeli kod źródłowy programu składa się z wielu plików, to należy stworzyć jeden plik, umieszczając w nim kody wszystkich plików składowych.

3. Plik musi zostać wysłany z poczty ZUT (zut.edu.pl).

3

(4)

4. Temat maila musi mieć postać: ALGO2 IS1 XXXY LAB06, gdzie XXXY to numer grupy (np. ALGO2 IS1 210C LAB06).

5. W pierwszych trzech liniach pliku z kodem źródłowym w komentarzach muszą znaleźć się:

- informacja identyczna z zamieszczoną w temacie maila (linia 1), - imię i nazwisko autora (linia 2),

- adres e-mail (linia 3).

6. Mail nie może zawierać żadnej treści (tylko załącznik).

7. W razie wykrycia plagiatu, wszytkie uwikłane osoby otrzymają za dane zadanie ocenę 0 punktów (co jest gorsze niż ocena 2 w skali {2, 3, 3.5, 4, 4.5, 5}).

4

Cytaty

Powiązane dokumenty

Uzupełnij poniższy tekst, wpisując brakujące wyrazy tak, aby informacja dotycząca budowy korzenia była prawdziwa. Kambium i fellogen odpowiadają za ...na ... Miazga wytwarza

[r]

Niewykluczone też, iż przy podejmo- waniu decyzji o zlokalizowaniu Kampusu 600-lecia Odnowienia Uniwersytetu, w tym Wydziału Fizyki, Astronomii i Informatyki Stosowanej,

funkcja / metoda to string(...) (format wy- niku wg uznania programisty, może zawierać np. rozmiar listy, wypis pewnej liczby elementów początkowych / końcowych, opcjonalnie adres

(b) zwrócenie danych i-tego elementu tablicy (argument: indeks i żądanego elementu (numerując od zera); wynik: dane i-tego elementu lub niepowodzenie w razie indeksu poza zakresem),

Każdy węzeł drzewa powinien zawierać: dane właściwe (lub wskaźnik na nie), wskaźnik na rodzica, wskaźniki na lewego i prawego potomka.. Samo drzewo powinno przechowywać wskaźnik

Każdy węzeł drzewa powinien zawierać: dane właściwe (lub wskaźnik na nie), wskaźnik na rodzica, wskaźniki na lewego i prawego potomka, flagę logiczną określającą

Dodawanie nowych elementów do tablicy mieszającej jest także operacją stałoczasową, przy czym ściśle rzecz biorąc tylko w sensie zamortyzo- wanym, co wynika z własności