Programowanie obiektowe Projekt pełen

advertisement
Programowanie obiektowe
Nazwa zadania
Projekt pełen - implementacja
“Drzewa”
Dzień, godzina
środa, 12:15
Imię i Nazwisko
Paweł Tarasiuk
Rok akademicki
2009/2010
Imię i Nazwisko
Grzegorz Graczyk
Opis programu
Projekt składa się z implementacji przydatnych struktur danych – grafów które nie mają cykli, czyli drzew. Istotą projektu jest
wykorzystanie polimorfizmu w celu zaimplementowania wielu drzew przy minimalnej koniecznej do tego liczbie kodu –
implementując kolejne drzewo zajmujemy się tylko tym, co jest dla niego specyficzne. Zaimplementowana została w ten sposób
np. lista “DendroList”, która dziedziczy po uniwersalnej klasie “Tree” (należy zauważyć, że lista dwukierunkowa jest po prostu
drzewem, w którym każdy wierzchołek ma dokładnie jednego syna). Bardziej praktyczne są przygotowane implementacje drzew
binarnych: kopca oraz drzew binarnych wyszukiwań. Poza zwykłym drzewem wyszukiwań binarnych przygotowane zostały
dziedziczące po nim szczególne implementacje dbające o zachowanie zrównoważenia drzewa – drzewa AVL oraz czerwono-czarne.
Poza samymi klasami drzew, oczywiście zaimplementowane zostały specjalne klasy do przechowywania wierzchołków oraz ich
własności. Każdy wierzchołek posiada wskaźnik na rodzica listę wskaźników dzieci, natomiast każde drzewo przechowuje wskaźnik
na swój korzeń.
Każde drzewo umożliwia dodawanie elementów na podstawie wartości (funkcja dodająca zwraca wskaźnik utworzonego elementu,
który można przechowywać), usuwanie na podstawie wskaźnika oraz “przeglądanie” drzewa – czyli wykonywanie zdefiniowanej
przez programistę funkcji dla każdego wierzchołka w kolejności inorder, preorder bądź postorder (wykonywany jest algorytm DFS).
Projekt zawiera także przykład użycia tej funkcji, dzięki któremu można obserwować drzewo, dodawać/usuwać elementy i
analizować wynikające z tego zmiany.
Przygotowana funkcja main stanowi prosty wiersz polecenia, służący do tworzenia drzew, dodawania/usuwania elementów,
sprawdzania czy element o danej wartości istnieje, wyświetlania bieżącego stanu drzewa oraz wykonywania funkcji specyficznych
dla drzewa danego typu (takich, jak “pop” dla kopca).
Przygotowane klasy oczywiście dają możliwości większe, niż te użyte w pliku wykonywalnym projektu. Prawdziwym zastosowaniem
jest stosowanie elementów tego projektu jako biblioteki, z której na pewno wiele razy skorzystamy. Posiadania własnej
implementacji pewnych struktur danych może okazać się dla nas pomocne podczas udziału w konkursach algorytmicznych, na
których można mieć przy sobie wydruki własnych kodów źródłowych przygotowanych wcześniej. Największe znaczenie będzie
jednak dla nas miała wiedza zdobyta podczas tworzenia projektu – implementacja drzew czerwono-czarnych oraz AVL była dla nas
interesującym doświadczeniem.
Dokumentacja techniczna - diagram klas
Dokumentacja techniczna - wybrane scenariusze działania
•
Przygotowany program stanowi prosty wiersz polecenia – istnieje kilka zdefiniowanych przez nas poleceń, które pozwala
utworzyć drzewo wybranego typu, zarządzać nim oraz obserwować powstające zmiany. Możliwe zmiany to dodanie oraz
usunięcie elementu o zadanej wartości. W przypadku kopca – dostępne są polecenia “pop” oraz “push”. W dowolnej chwili
można wyświetlić zawartość drzewa w elegancki sposób, albo po prostu wypisać wartości elementów w kolejności inorder. W
momencie utworzenia nowego drzewa, stare zostaje zwolnione z pamięci, a dalsze operacje przeprowadzane są na nowym
drzewie. W dowolnym momencie można także opuścić program.
Programowanie obiektowe
•
Projekt pełen - implementacja
Klasy przygotowane w ramach projektu mogą zostać wykorzystane poza nim – projekt stanowi tak naprawdę bibliotekę z
bardzo uniwersalnymi klasami. Można np. wykorzystać naszą implementację kopca w celu przeprowadzenia sortowania przez
kopcowanie, stworzyć słownik wykorzystujący nasze drzewo AVL, albo wykorzystać nasze drzewo czerwono-czarne zamiast
szablonu “set” z biblioteki STL. Praktycznie wszędzie, gdzie potrzebna jest zaimplementowana przez nas struktura danych,
można wykorzystać właśnie naszą, zawartą w projekcie implementację.
Dokumentacja techniczna - inne elementy nie opisane powyżej
Niektóre klasy zawierają specyficzne dla nich metody, pozwalające używać ich w sposób bardziej intuicyjny oraz zgodny ze
szczególnym przeznaczeniem. Dla elementu zaimplementowanej przez nas listy istnieją metody getNext, getPrev, setNext oraz
setPrev. Kopiec posiada natomiast metody “pop” i “push”.
Zaletą pisanego przez nas kodu jest także brak polonizacji nazw – dzięki temu przygotowane przez nas klasy mogłyby się stać
elementem jakiegoś innego projektu, rozwijanego przez osoby nie znające języka polskiego.
Zmiany w stosunku do implementacji projektu uproszczonego
Zdecydowaliśmy się na to, aby niektóre szczególne drzewa binarnych wyszukiwań korzystały po prostu z generycznych klas
opisujących element drzewa binarnego, zamiast wprowadzać dziedziczące po nich własne klasy wierzchołków drzew. Po prostu
okazało się to niepotrzebne, a dzięki uniknięciu tego projekt jest odrobinę lżejszy.
Zmiany w odniesieniu do projektu pełnego
Do projektu zostało dodane nowe drzewo: kopiec dwumianowy. Posiada on interfejs identyczny ze zwykłym kopcem, choć nie
dziedziczy z niego.
Ponadto wprowadzono nowe klasy abstrakcyjne: Searchable oraz Popable. Klasy te nie posiadają żadnych pól i posiadają po jednej
metodzie czysto wirtualnej – odpowiednio: TreeElement* findElement(int) oraz int pop(). Ich wykorzystanie za pomocą
wielodziedziczenia pozwala stwierdzić czy dany obiekt oferuje odpowiednie metody.
Dokumentacja użytkownika
Osoba uruchamiająca przygotowany przez nas projekt może:
•
Przeczytać początkowe wskazówki, które dadzą duże szanse na to, że użytkownik po prostu poradzi sobie ze wszystkim kierując
się intuicją.
•
Utworzyć nowe drzewo za pomocą polecenia “tree NUMER”, według początkowej wskazówki. Od tej pory dotychczasowe drzewo
(o ile istniało) zostanie zwolnione z pamięci, a nowo utworzone drzewo stanie sie aktwyne.
•
Dodać element do drzewa poleceniem “add element”.
•
Wyświetlić stan drzewa poleceniem “ls”.
•
Wypisać wartości elementów w kolejności inorder poleceniem “inorder”.
•
Dla drzew wyszukiwań binarnych (czyli także czerwono-czarnych i AVL) – rozstrzygnąć, czy element o danej wartości znajduje
się w drzewie poleceniem “find WARTOŚĆ” oraz usunąć pierwszy znaleziony element o danej wartości poleceniem “rm
WARTOŚĆ”.
•
Dla kopca: poznać wartość największego elementu a zarazem usunąć go za pomocą polecenia “pop” oraz dodawać elementy
intuicyjnym w przypadku kopca poleceniem “push”.
•
Opuścić program wpisując “quit”.
Miejsce na uwagi prowadzącego
Download