związek między funkcją hashującą a indeksem bucketa

0

Witam

  1. Nie wiem jak dodac własną funkcje hashującą do unordered_seta bądź mapy. Np. takie coś jak niżej powinno zadziałac a nie działa. Hash "10" w obu przypadkach jest taki sam jakaś milionowa liczba, nie wywołuje mi się w ogóle operator (). CO może być poniżej źle?
class HashClass
{
public:
	size_t operator()(const string& str) const
	{
		cout << "hash dla " << str << " " <<std::stoi(str) << endl;
		return std::stoi(str); //example "10" -> hash = 10
	}
};

	unordered_set<string> zbior2{ "7", "3", "9", "10", "1" };
	printIter(zbior2.begin(), zbior2.end());
	unordered_set<string>::hasher funkcjaHashujaca = zbior2.hash_function();
	cout << funkcjaHashujaca("10") << endl;

	unordered_set<string, HashClass> zbior3({ "7", "3", "9", "10", "1" }, 31, HashClass()); //31 - minimum number of buckets, there will be 32
	printIter(zbior3.begin(), zbior3.end());
	unordered_set<string, HashClass>::hasher funkcjaHashujaca2 = zbior3.hash_function();
	cout << funkcjaHashujaca2("10") << endl;
  1. Nie wiem też jaki jest związek między indeksem bucketa a wartości zwracanej przez funckję hashującą. Powyżej hash dla "10" w obu przypadkach ma wartość jakąś bardzo dużą 4 miliony coś. Na pewno funkcja hashujaca nie zwraca indeksu bucketa co można sprawdzic pętlą:
	for (auto& x : zbior3)
		cout << "hash value: " << HashClass()(x) << " => " << x << " bucket no " << zbior3.bucket(x) << endl;
	cout << zbior3.bucket_count() << endl;

Co do drugiego problemu to boję się że na rozmowie kwalifikacyjnej rekrutujący każe uporządkować mi obiekty (tak po prostu jako sztuka dla sztuki bo wiadomo że ten kontener nie jest do tego) w unordered_mapie bez pisania jakichś skomplikowanych pętli for, tylko tak już przy kontruktorze i z powyższego wydaje się że sie nie da, że to kontener którego nie uporządkujemy bez jakiegoś większego kawałka kodu.

0

OK, oświeciło mnie, wcześniej już miałem zdefiniowaną strukturą HashClass i on ją brał zamiast klasy HashClass:

struct HashClass
{
	size_t operator()(const string& str) const
	{
		return hash<string>()(str);
	}
};

Po poprawieniu błędu mogę powiedzieć że problem 1 się rozwiązał natomiast co do 2 to numer bucketa odpowiada wartości funkcji hashującej. Podejrzewam, że kontener przy wyliczaniu indeksu z wartości hasha korzysta z jakiegoś modulo w którym biora udział liczba bucketów, load_factor itp.

0

W najprostszym przypadku z tego co mi wiadomo to adres = hash % hashmap_size.

0

dokładnie po wyliczeniach z outputu z konsoli wyszło mi że numer indeksu jest równy reszcie z dzielenia wartości hasha przez liczbę bucketów (bucket_count()).

0

A po co ci to wiedzieć, skoro używasz gotowych kontenerów, które robią same podział na kubełki?
Teoria mówi, że zwykle to liczba kubełków jest liczbą pierwszą (na tyle dużą, by jedn kubełek zawierał mało elementów a na tyle małą, żeby nie było pustych kubełków), w praktyce by optymalizować przyporządkowania do kubełka stosuje się coś co łatwo zamienić na proste dla procesora operacje (potęga dwójki, lub coś bardzo do tego zbliżonego).
Z tego co mi wiadomo, STLowe kontenery dynamicznie dobierają ilość kubełków.

0

typowo na rozmowe kwalifikacyjną, bo na nich różni szaleni rekruterzy są. W pracy wiadomo taka wiedza nie jest potrzebna.
Co do tematu to zauwazyłem, że nawet jak mam stringi "9", "4", itp. i dla nich hashe to 9, 4, itp oraz numery bucketow to 9, 4 itp. to i tak jak jedziesz po kontenerze od begin() do end() i wyświetlasz elementy to on i tak ci nie wyświetla w kolejności 1,2,...4,...9 ani nawet w kolejności w jakiej dodawałes elemnty do kontenera tylko wyświetla to losowo jakoś w zalezności od zdefiniowanego hasha. Ale mam nadzieję że już rekruter nie będzie pytał co zrobić z kontenerem unordered_set by iterując go wyświetlał elementy w kolejności rosnącej.:)

1 użytkowników online, w tym zalogowanych: 0, gości: 1