Algorytmy i Struktury Danych Anna Paszyńska
Tablica dynamiczna szablon Array
Zbiory
Zbiory template <typename T> class Container {public: virtual ~Container() { }; virtual int Count() const = 0; virtual bool IsEmpty() const {return Count()==0;} virtual bool IsFull() const { return false; } virtual void MakeNull() = 0; virtual void Accept(Visitor<T> & visitor) = 0; };
Zbiory template <typename T> class Set : public virtual Container<T> { protected: unsigned int count; unsigned int universesize; public: Set (unsigned int n) : universesize (n) {} unsigned int UniverseSize(){return universesize;} int Count() const {return count;}; };
Zbiór jako tablica Można użyć albo szablonu Array albo szablonu std::vector. Oba to tablice o dynamicznie ustalanej długości. My zastosujemy szablon Array.
Zbiór jako tablica Zbiór jest reprezentowany jako tablica wartości boolowskich o długości N. Rozważmy element, któremu przyporządkowano liczbę i: jeśli w i-tej komórce tablicy jest true, to należy on do danego zbioru, a jeśli jest false, to nie należy Implementując klasę SetAsArray przyjmujemy, że: - jako argumenty dla metod operujących na elementach zawsze podajemy int (mapowanie między np. województwami a liczbami wykonywane przez kogoś innego -rozmiar uniwersum podaje się konstruktorowi zbioru - Operacje typu: porównywanie, sumowanie itd.. można wykonywać tylko, gdy oba zbiory są nad tym samym uniwersum
Zbiór jako tablica class SetAsArray : public Set<int> { Array<bool> _array; public: SetAsArray (unsigned int); void MakeNull();//metody z containera void Accept(Visitor<int> & visitor); virtual bool IsFull() const{return(count==universesize);}; void Insert (int object); bool IsMember (int object) const; void Withdraw (int object); friend SetAsArray operator + (SetAsArray const&, SetAsArray const&); friend SetAsArray operator (SetAsArray const&, SetAsArray const&); friend SetAsArray operator * (SetAsArray const&, SetAsArray const&); friend bool operator == (SetAsArray const&, SetAsArray const&); friend bool operator <= (SetAsArray const&, SetAsArray const&); }; friend- funkcja uzyska prawo dostępu do prywatnych elementów danej klasy.
Zbiór jako tablica - implementacja Konstruktor pobiera jeden argument N oznaczający rozmiar zbioru uniwersalnego. (uniwersalnego więc również rozmiar tablicy boolowskiej). Konstruktor tworzy pusty zbiór inicjalizując tablicę wartościami false. Złożoność czasowa konstruktora O(n). Metoda Insert wstawia element do zbioru. Odpowiedni element tablicy jest ustawiany na true, aby zaznaczyć, że podany obiekt został wstawiony do zbioru. Uwaga: zbiór nie posiada wstawianych obiektów! Wstawione obiekty są reprezentowane pośrednio poprzez indeksy tablicy. Złożoność czasowa operacji wstawiania O(1).
Zbiór jako tablica - implementacja Metoda IsMember stosowana jest do sprawdzania, czy dany element należy do zbioru. Funkcja zwraca prawdę, gdy element należy do zbioru i fałsz w przeciwnym wypadku. Złożoność czasowa O(1). Metoda Withdraw usuwa element ze zbioru. Ustawia ona odpowiedni element tablicy boolowskiej na false. Złożoność czasowa O(1). Uwaga: Należy pamiętać o modyfikacjach licznika count.
Zbiór jako tablica - implementacja Przeciążone zostały następujące operatory: operator+ (suma zbiorów) operator* (iloczyn zbiorów) operator- (różnica zbiorów)
Zbiór jako tablica - implementacja Zadanie 1. Zaimplementuj operator sumy: SetAsArray operator + (SetAsArray const& s, SetAsArray const& t) Operator sumy pobiera dwie referencje do instancji klasy SetAsArray: s oraz t. Wynik jest typu SetAsArray. Implementacja wymaga, aby obydwa zbiory s oraz t miały taki sam rozmiar. Wynik również będzie zbiorem o tym samym rozmiarze. Operator ten tworzy nową tablicę wynikową i oblicza wymagane wartości tablicy. i-ty element tablicy będzie przyjmował wartość true, gdy i-ty element s przyjmuje wartość true lub i-ty element t przyjmuje wartość true. Złożoność czasowa O(N) class SetAsArray : public Set<int> { Array<bool> _array; public: friend SetAsArray operator + (SetAsArray const&, SetAsArray const&);
Zbiór jako tablica - implementacja SetAsArray operator + (SetAsArray const& s, SetAsArray const& t) { if (s.universesize == t.universesize) SetAsArray result (s.universesize); for (unsigned int i = 0; i < s.universesize; ++i) result._array [i] = s._array [i] t._array [i]; return result; } Uwaga: Należy pamiętać o modyfikacjach licznika count.
Zbiór jako tablica - implementacja Przeciążone zostały również operatory porównania dla zbiorów: Operator== (równość zbiorów) Operator<= (zawieranie) Obydwa operatory zwracają wartości boolowskie.
Zbiór jako tablica - implementacja Przeciążone zostały również operatory porównania dla zbiorów: Operator== (równość zbiorów) Operator<= (zawieranie) Obydwa operatory zwracają wartości boolowskie. bool operator == (SetAsArray const& s,setasarray const& t) { if (s.universesize == t.universesize) for (unsigned int i = 0; i < s.universesize;++i) if (s._array [i]!= t._array [i]) return false; return true; } Pesymistyczny czas wykonania O(N)
Zbiór jako tablica - implementacja Zad.2. Stworzyć klasę AddingVisitor wizytatora, który oblicza sumę elementów zbioru.
Zbiór jako tablica - implementacja Zad.2. Stworzyć klasę AddingVisitor wizytatora, który oblicza sumę elementów zbioru. template <typename T> class Visitor { public: virtual void Visit (T& element) = 0; virtual bool IsDone () const{ return false; } }; 10)Tworzymy klasę AddingVisitor dziedziczącą z klasy Visitor 2) Implementujemy metodę Accept dla klasy SetAsArray (przegląda wszystkie elementy zbioru wywołując v.visit()
Zad.2. 1) Tworzymy klasę AddingVisitor dziedziczącą z klasy Visitor class AddingVisitor:public Visitor<int> { Zbiór jako tablica - implementacja protected: int sum; public: AddingVisitor():sum(0){}; void Visit(int&); int Sum(){return sum;} }; void AddingVisitor::Visit(int& obj) { sum=sum+obj;}
Zad.2. 2) Implementujemy metodę Accept dla klasy SetAsArray (przegląda wszystkie elementy zbioru wywołując v.visit() void SetAsArray::Accept (Visitor<int>& v) { for (int item = 0; item < (int) universesize; ++item) if (_array [item] == true) v.visit(item); } Zbiór jako tablica - implementacja
Zbiór jako tablica - implementacja Zad.3. Zaimplementuj iterator dla klasy SetAsArray
Zbiór jako tablica - implementacja template <typename T> class SetAsArray : public Set<int> { Array<bool> _array; class Iter//deklaracja zapowiadająca public: Iterator<T>&NewIterator(); }; template <typename T> class SetAsArray<T> ::Iter:public Iterator<T> {... }
Przeglądanie zawartości iteratory isdone Metoda IsDone w celu wyjścia z pętli while. Metoda ta zwraca false jeśli iterator nadal wskazuje na jakiś obiekt kontenera, oraz wartość true w przeciwnym przypadku. (gdy wszystkie obiekty zawarte w kontenerze zostały odwiedzone) operator* Operator dereferencji wskaźnika, jest używany, aby dostać się do obiektu na który iterator aktualnie wskazuje. Wynikiem wywołania tej funkcji, gdy cały kontener jest wyczerpany jest referencja do instancji klasy NullObject operator++ operator używany do przesunięcia iteratora do następnego obiektu w kontenerze. Jeżeli kontener jest wyczerpany, operator inkrementacji nie zmienia wartości iteratora