struct Elem { char *klucz; int wartosc; /* ... */ }; // zawiera parę (klucz, wartość) void Wstaw(Elem *e); // wstawianie pary (klucz, wartość) void Usun(Elem *e); // usuwanie pary (klucz, wartość) Elem *Szukaj(char *klucz); // znajdowanie pary z podanym kluczemw jak najkrótszym czasie ...
Uwaga 1: powyżej założyliśmy że klucz jest napisem a wartość jest liczbą całkowita; ta konwencja obowiązuje we wszystkich zadaniach z tej lekcji.
Zauważmy że jeśli zbiór wszystkich kluczy nie jest zbyt duży, to prawdopodobnie możemy każdy klucz utożsamić z pewną liczbą całkowitą, i użyć tej liczby jako indeksu do tablicy wskazującego element zawierający wartość odpowiadająca kluczowi. Co jednak zrobić jeśli zbiór wszystkich kluczy jest "gigantyczny" ? Nie możemy przecież używać "gigantycznej tablicy" !!!
Wtedy problem można rozwiązać przy pomocy tzw funkcji haszującej:
Dobra funkcja haszująca to taka, że przeciwobrazy elementów ze zbioru {0, ..., m-1} są "w miarę" równej mocy.
Uwaga 2: w poniższych zadaniach często traktujemy "klucz" jako
dużą liczbę całkowitą: litery klucza (duże i małe) należy traktować jako
"cyfry" z zakresu [0 .. 2*26-1], jest to więc liczba zapisana przy podstawie
2*26=52.
Zadanie 32
struct Elem { char *klucz; int wartosc; /* ... */ }; void Wstaw(Elem *e); void Usun(Elem *e); // ma działać w stałym czasie !!! Elem *Szukaj(char *klucz);używając następujących funkcji haszujących:
Wskazówka: jak obliczyć wartość "k % m"
jeśli "k" jest bardzo dużą liczbą całkowitą ?
niech "k_i" oznacza kolejne cyfry klucza (i=0,
..., q-1), zapisanego przy podstawie "b", przy czym "k_0" jest najbardzej
znaczącą cyfrą; możemy obliczyć wartość liczbową klucza następująco:
s:=k_0;
for
i:=1 to q-1 do s := s*b + k_i
// "s" zawiera wartość liczbową
"k"
okazuje się że wartość "k % m" można obliczyć
analogicznie (oczywiscie wymaga to dowodu !?!):
s:=k_0;
for
i:=1 to q-1 do s := ( s*b + k_i ) mod m
// "s" zawiera wartość liczbową
"k % m"
// unikamy dużych wartości
"s" !!!
.
każde słowo traktujemy jako "klucz", natomiast jego nr porządkowy jako "wartość"
dla danego "pliku ze słowami" należy wypróbować wszystkie funkcje haszujące wymienione wyżej
dla każdej funkcji haszującej należy wykonać następujące czynności: