====== Tablice haszujące ======
Termin zajęć: 8./9. maja 2012
===== Do przygotowania - teoria na temat: =====
- Rodzaje haszowania
* haszowanie bezpośrednie
* haszowanie modularne
* haszowanie przez mnożenie
* haszowanie uniwersalne
- Problem konfliktów podczas haszowania
- Sposoby rozwiązywania konfliktów
* Metoda łańcuchowa
* Metoda adresowania otwartego
===== Do pobrania: =====
Proszę pobrać archiwum {{:pl:dydaktyka:asd:cwiczenia:hashing.zip|}}, w którym znajdują się pliki potrzebne do wykonania ćwiczeń na zajęciach.
Oto krótki opis plików:
* ''finduniversumsize.cpp'' - program obliczający optymalną wielkość tablicy haszującej na podstawie przewidywanej ilości danych i średniej długości łańcucha.
* ''findnextprime.cpp'' - program wyszukujący kolejną liczbę pierwszą.
* ''hchain.h'' + ''hchain.cpp'' - moduł zawierający klasę implementującą tablicę haszującą z łańcuchową metodą rozwiązywania konfliktów.
* ''hopen.h'' + ''hopen.cpp'' - moduł zawierający klasę implementującą tablicę haszującą z metodą adresowania otwartego. Moduł ten nie wspiera poprawnie usuwania/usuniętych wartości - uzupełnienie będzie jednym z zadań.
* ''mainmodular.cpp'' - niezobowiązujący plik pokazujący przykładowe wykorzystanie klas.
Proszę zapoznać się ze strukturą i działaniem poszczególnych klas, przetestować kod i w miarę możliwości przynieść na zajęcia laptopy wraz z wszystkimi plikami (można umówić się na pracę w parach/trójkach i na zajęciach pracować we 2-3 osoby przy jednym komputerze).
===== Ćwiczenia i zadania implementacyjne =====
Punkty oznaczone 8-) należy samodzielnie wykonać w domu, pozostałe punkty stanowią opis, wprowadzenie, zachętę do samodzielnych testów.
==== Zadanie 1 ====
* W pobranej paczce jest program ''finduniversumsize.cpp'' który służy do wyznaczania wartości //m// na podstawie ilości przechowywanych danych i zakładanej średniej długości listy.
* Jest też moduł ''hchain'' który jest klasą realizującą tablicę haszującą z łańcuchową metodą rozwiązywania konfliktów.
* Zadaniem jest praktyczne przetestowanie tej metody rozwiązywania konfliktów w tablicy o rozmiarze ''3584'' w której zakładamy że średnia długość listy wynosi ''7''.
* Proszę zmodyfikować istniejący program, który:
* tworzy dwie globalne funkcje haszujące typu:int f(int val)
* Obie funkcje obliczają indeks w tablicy haszującej przy pomocy działania modulo: return val%m
gdzie:
* w pierwszej funkcji haszującej ''m = 512 (3584/512 = 7)'',
* wartość //m// w drugiej funkcji wyliczona jest przy pomocy programu ''finduniversumsize''.
* tworzy dwa obiekty klasy ''hash_chain'', których konstruktor przyjmuje następujące wartości:
* W pierwszym obiekcie:
* jako rozmiar tablicy: ''512'',
* wskaźnik do pierwszej funkcji haszującej.
* W drugim obiekcie:
* jako rozmiar tablicy: wartość obliczoną wcześniej przy pomocy programu ''finduniversumsize'',
* wskaźnik do drugiej funkcji haszującej.
* Do każdego obiektu należy wstawić ''3584'' losowych wartości z przedziału ''[0 do np. 10000]''.
* Po wstawieniu należy wyświetlić informacje o stanie tablicy przy pomocy metody: hash_chain::printInfo()
* Powyższe dwie czynności można powtórzyć kilkakrotnie obserwując rozmieszczenie elementów w tablicy, oraz średnie odchylenie od średniej.
* Można zauważyć że w takim przypadku obie funkcje haszujące są mniej więcej tak samo dobre (jednak minimalnie lepsze rezultaty daje ta z obliczoną wartością //m//).
* Można także próbować manewrować parametrami i obserwować co się dzieje.
* 8-) Kolejnym krokiem zadania jest wygenerowanie pesymistycznego przypadku dla pierwszej funkcji haszującej: po wylosowaniu wartości przesuwamy jej bity o np. ''2'' w lewo i ustawiamy najmniej znaczący
* Obserwujemy co się dzieje. W obiekcie pierwszym rozmieszczenie wartości jest dużo mniej równomierne -> wzrasta średnie odchylenie.
* Można było się tego spodziewać ponieważ reszta z dzielenia przez wartość będącą ''p''-tą potęgą ''2'' to nic innego jak p najmniej znaczących bitów liczby. Zatem wszystkie generowane indeksy mają takie same wartości dwóch ostatnich bitów.
* Proszę analogicznie przesunąć i dowolnie ustawić ''4'' bity -> wynik: jeszcze gorsza jakość.
* 8-) Dla drugiej funkcji haszującej też bez problemu można wyznaczyć zestaw danych pesymistycznych -> JAK? Proszę dopisać operację "psującą" dane dla drugiej funkcji.
* 8-) Proszę "zepsuć" dane dla pierwszej i drugiej funkcji jednocześnie. Jak teraz poprawić rozłożenie danych w tablicy haszującej?
==== Zadanie 2 ====
8-) W paczce znajdują się pliki ''hopen.cpp'' i ''hopen.h'' które zawierają definicję klasy realizującej tablicę haszującą w której konflikty są rozwiązywane metodą adresowania otwartego.
W tej klasie brakuje obsługi wartości usuniętych. Zadanie polega na uzupełnieniu podanej klasy o obsługę tych wartości.
\\ Rozwiązanie jest krótkie: należy:
- W pliku nagłówkowym dopisać definicję nowej wartości np.#define STS_DLTD 2
- W pliku ''cpp'' uzupełnić:
- Metodę ''insert''
- Metodę ''remove''
- Ewentualnie w metodzie wypisującej wartości ''printValues'' dopisać jeden warunek:else if(_ststab[i] == STS_DLTD)
cout << "DLTD, ";