hash table c programs implement hash table
Ten samouczek wyjaśnia C ++ tabele skrótów i mapy skrótów. Dowiesz się również o aplikacjach Hash Table i implementacji w C ++:
Haszowanie to technika, za pomocą której możemy odwzorować dużą ilość danych na mniejszą tabelę za pomocą „funkcji skrótu”.
Używając techniki mieszania, możemy przeszukiwać dane szybciej i wydajniej w porównaniu z innymi technikami wyszukiwania, takimi jak wyszukiwanie liniowe i binarne.
Zrozummy technikę haszowania na przykładzie w tym samouczku.
=> Przeczytaj serię szkoleń Easy C ++.
Czego się nauczysz:
- Haszowanie w C ++
- Implementacja tablicy skrótów w C ++
- Zastosowania haszowania
- Wniosek
Haszowanie w C ++
Weźmy przykład biblioteki uniwersyteckiej, w której znajdują się tysiące książek. Książki są uporządkowane według tematów, działów itp. Jednak każda sekcja będzie zawierać wiele książek, co utrudni ich wyszukiwanie.
W ten sposób, aby przezwyciężyć tę trudność, przypisujemy każdej książce unikalny numer lub klucz, dzięki czemu natychmiast znamy lokalizację książki. Rzeczywiście osiąga się to poprzez mieszanie.
Kontynuując nasz przykład z biblioteki, zamiast identyfikować każdą książkę na podstawie jej działu, tematu, sekcji itp., Co może skutkować bardzo długim ciągiem, obliczamy unikalną wartość całkowitą lub klucz dla każdej książki w bibliotece za pomocą unikalnej funkcji i przechowuj te klucze w osobnej tabeli.
Wspomniana powyżej unikalna funkcja nosi nazwę „Funkcja skrótu”, a oddzielna tabela nosi nazwę „Tabela skrótów”. Funkcja skrótu służy do mapowania podanej wartości na konkretny unikatowy klucz w tabeli skrótów. Skutkuje to szybszym dostępem do elementów. Im wydajniejsza jest funkcja haszująca, tym wydajniejsze będzie mapowanie każdego elementu na unikalny klucz.
Rozważmy funkcję skrótu h (x) który odwzorowuje wartość „ x ' w ' x% 10 ”W tablicy. Dla podanych danych możemy zbudować tablicę haszującą zawierającą klucze lub kody skrótu lub skróty, jak pokazano na poniższym schemacie.
Na powyższym diagramie widzimy, że wpisy w tablicy są mapowane na swoje pozycje w tablicy mieszającej za pomocą funkcji skrótu.
Możemy więc powiedzieć, że haszowanie jest realizowane w dwóch krokach, jak wspomniano poniżej:
# 1) Wartość jest konwertowana na unikatowy klucz liczby całkowitej lub skrót przy użyciu funkcji skrótu. Jest używany jako indeks do przechowywania oryginalnego elementu, który wpada do tablicy skrótów.
Na powyższym diagramie wartość 1 w tablicy hash jest unikalnym kluczem do przechowywania elementu 1 z tablicy danych podanej na LHS diagramu.
c ++ char na string
#dwa) Element z tablicy danych jest przechowywany w tablicy haszującej, skąd można go szybko pobrać za pomocą skrótu klucza. Na powyższym diagramie widzieliśmy, że zapisaliśmy wszystkie elementy w tablicy mieszającej po obliczeniu ich odpowiednich lokalizacji za pomocą funkcji skrótu. Możemy użyć następujących wyrażeń, aby pobrać wartości skrótu i indeks.
hash = hash_func(key) index = hash % array_size
Funkcja skrótu
Wspomnieliśmy już, że efektywność mapowania zależy od wydajności używanej przez nas funkcji skrótu.
Funkcja skrótu zasadniczo powinna spełniać następujące wymagania:
- Łatwe do obliczenia: Funkcja skrótu powinna być łatwa do obliczenia unikatowych kluczy.
- Mniej kolizji: Gdy elementy są zrównane z tymi samymi wartościami kluczowymi, następuje kolizja. W używanej funkcji skrótu powinno być możliwie jak najmniej kolizji. Ponieważ kolizje muszą wystąpić, musimy zastosować odpowiednie techniki rozwiązywania kolizji, aby zająć się zderzeniami.
- Jednolita dystrybucja: Funkcja skrótu powinna zapewniać równomierną dystrybucję danych w tabeli skrótów, a tym samym zapobiegać klastrowaniu.
Hash Table C ++
Tabela skrótów lub mapa skrótów to struktura danych, która przechowuje wskaźniki do elementów oryginalnej tablicy danych.
W naszym przykładzie z biblioteką tabela skrótów dla biblioteki będzie zawierać wskaźniki do każdej książki w bibliotece.
Posiadanie wpisów w tablicy haszującej ułatwia wyszukanie konkretnego elementu tablicy.
Jak już widzieliśmy, tablica mieszająca używa funkcji skrótu do obliczenia indeksu w tablicy segmentów lub przedziałów, za pomocą których można znaleźć żądaną wartość.
Rozważ inny przykład z następującą tablicą danych:
Załóżmy, że mamy tabelę skrótów o rozmiarze 10, jak pokazano poniżej:
Teraz użyjmy funkcji skrótu podanej poniżej.
Hash_code = Key_value % size_of_hash_table
Będzie to równoznaczne z Hash_code = Key_value% 10
Korzystając z powyższej funkcji, mapujemy wartości kluczy do lokalizacji tabeli skrótów, jak pokazano poniżej.
Pozycja danych | Funkcja skrótu | Hash_code |
---|---|---|
22 | 22% 10 = 2 | dwa |
25 | 25% 10 = 5 | 5 |
27 | 27% 10 = 7 | 7 |
46 | 46% 10 = 6 | 6 |
70 | 70% 10 = 0 | 0 |
89 | 89% 10 = 9 | 9 |
31 | 31% 10 = 1 | jeden |
Korzystając z powyższej tabeli, możemy przedstawić tabelę skrótów w następujący sposób.
Zatem gdy musimy uzyskać dostęp do elementu z tablicy skrótów, wykonanie wyszukiwania zajmie O (1) czasu.
Kolizja
Zwykle obliczamy kod skrótu za pomocą funkcji skrótu, abyśmy mogli odwzorować wartość klucza na kod skrótu w tabeli skrótów. W powyższym przykładzie tablicy danych wstawmy wartość 12. W takim przypadku hash_code dla wartości klucza 12 będzie wynosić 2. (12% 10 = 2).
Ale w tabeli skrótów mamy już mapowanie na klucz-wartość 22 dla hash_code 2, jak pokazano poniżej:
Jak pokazano powyżej, mamy ten sam kod skrótu dla dwóch wartości, 12 i 22, tj. 2. Gdy co najmniej jedna wartość kluczowa odpowiada tej samej lokalizacji, dochodzi do kolizji. Zatem lokalizacja kodu skrótu jest już zajęta przez jedną wartość klucza i istnieje inna wartość klucza, która musi zostać umieszczona w tej samej lokalizacji.
W przypadku haszowania, nawet jeśli mamy tablicę haszującą o bardzo dużych rozmiarach, na pewno wystąpi kolizja. Dzieje się tak, ponieważ ogólnie znajdujemy małą unikalną wartość dla dużego klucza, dlatego jest całkowicie możliwe, że jedna lub więcej wartości ma ten sam kod skrótu w dowolnym momencie.
Biorąc pod uwagę, że kolizja jest nieunikniona podczas haszowania, zawsze powinniśmy szukać sposobów, aby zapobiec kolizji lub rozwiązać ją. Istnieją różne techniki rozwiązywania kolizji, które możemy zastosować, aby rozwiązać kolizję występującą podczas haszowania.
Techniki rozwiązywania kolizji
Poniżej przedstawiono techniki, które możemy zastosować, aby rozwiązać kolizję w tabeli skrótów.
Oddzielne łańcuchowanie (otwarte haszowanie)
Jest to najpopularniejsza technika rozwiązywania kolizji. Jest to również znane jako otwarte haszowanie i jest realizowane za pomocą połączonej listy.
jak pisać skrypty testów automatyzacji
W technice oddzielnych łańcuchów każdy wpis w tablicy skrótów jest połączoną listą. Gdy klucz pasuje do kodu skrótu, jest wprowadzany na listę odpowiadającą temu konkretnemu kodowi skrótu. Tak więc, gdy dwa klucze mają ten sam kod skrótu, oba wpisy są umieszczane na połączonej liście.
W powyższym przykładzie poniżej przedstawiono oddzielne łańcuchy.
Powyższy diagram przedstawia tworzenie łańcuchów. Tutaj używamy funkcji mod (%). Widzimy, że gdy dwie wartości klucza są równe temu samemu kodowi skrótu, wówczas łączymy te elementy z tym kodem skrótu za pomocą połączonej listy.
Jeśli klucze są równomiernie rozmieszczone w tabeli skrótów, średni koszt wyszukiwania określonego klucza zależy od średniej liczby kluczy na tej połączonej liście. W ten sposób oddzielne tworzenie łańcuchów pozostaje skuteczne nawet wtedy, gdy liczba wejść jest większa niż gniazd.
Najgorszym przypadkiem w przypadku oddzielnego tworzenia łańcuchów jest sytuacja, gdy wszystkie klucze są równe temu samemu kodowi skrótu, a zatem są wstawiane tylko do jednej połączonej listy. Dlatego musimy poszukać wszystkich wpisów w tablicy skrótów i kosztów, które są proporcjonalne do liczby kluczy w tabeli.
Sondowanie liniowe (otwarte adresowanie / zamknięte haszowanie)
W technice adresowania otwartego lub sondowania liniowego wszystkie rekordy wejściowe są przechowywane w samej tablicy skrótów. Gdy klucz-wartość jest mapowany na kod skrótu, a pozycja wskazywana przez kod skrótu nie jest zajęta, wartość klucza jest wstawiana w tej lokalizacji.
Jeśli pozycja jest już zajęta, to za pomocą sekwencji sondowania wartość klucza jest wstawiana do następnej pozycji, która nie jest zajęta w tablicy haszującej.
W przypadku sondowania liniowego funkcja skrótu może się zmienić, jak pokazano poniżej:
hash = hash% hashTableSize
hash = (hash + 1)% hashTableSize
hash = (hash + 2)% hashTableSize
hash = (hash + 3)% hashTableSize
Widzimy, że w przypadku sondowania liniowego odstęp między szczelinami lub kolejnymi sondami jest stały, tj. 1.
Na powyższym diagramie widzimy, że w 0thlokalizację wprowadzamy 10 za pomocą funkcji skrótu „hash = hash% hash_tableSize”.
Teraz element 70 równa się również położeniu 0 w tablicy skrótów. Ale to miejsce jest już zajęte. Dlatego używając sondowania liniowego znajdziemy następną lokację, która jest 1. Ponieważ ta lokacja nie jest zajęta, umieszczamy klucz 70 w tym miejscu, jak pokazano za pomocą strzałki.
Wynikowa tabela skrótów jest pokazana poniżej.
Sondowanie liniowe może cierpieć na problem „pierwotnego skupiania się”, w którym istnieje szansa, że komórki ciągłe mogą zostać zajęte, a prawdopodobieństwo wstawienia nowego elementu zostanie zmniejszone.
Również jeśli dwa elementy otrzymają tę samą wartość w pierwszej funkcji skrótu, to oba te elementy będą podlegać tej samej sekwencji sondy.
Sondowanie kwadratowe
Sondowanie kwadratowe jest tym samym, co sondowanie liniowe, a jedyną różnicą jest interwał używany do sondowania. Jak sama nazwa wskazuje, technika ta wykorzystuje odległość nieliniową lub kwadratową do zajmowania szczelin w przypadku kolizji zamiast odległości liniowej.
W przypadku sondowania kwadratowego odstęp między szczelinami jest obliczany przez dodanie dowolnej wartości wielomianu do już zaszyfrowanego indeksu. Technika ta w znacznym stopniu ogranicza tworzenie klastrów pierwotnych, ale nie poprawia się po grupowaniu wtórnym.
Podwójne haszowanie
Technika podwójnego haszowania jest podobna do sondowania liniowego. Jedyną różnicą między podwójnym haszowaniem a sondowaniem liniowym jest to, że w technice podwójnego haszowania interwał używany do sondowania jest obliczany przy użyciu dwóch funkcji skrótu. Ponieważ stosujemy funkcję skrótu do klucza jeden po drugim, eliminuje to zarówno pierwotne, jak i wtórne grupowanie.
Różnica między łańcuchem (otwarte haszowanie) a liniowym sondowaniem (otwarte adresowanie)
Łańcuch (otwarte haszowanie) | Sondowanie liniowe (adresowanie otwarte) |
---|---|
Kluczowe wartości można przechowywać poza tabelą za pomocą oddzielnej połączonej listy. | Kluczowe wartości powinny być przechowywane tylko w tabeli. |
Liczba elementów w tabeli skrótów może przekraczać rozmiar tabeli skrótów. | Liczba elementów obecnych w tablicy haszującej nie przekroczy liczby indeksów w tablicy haszującej. |
Delecja jest skuteczna w technice łączenia. | Usunięcie może być kłopotliwe. Można tego uniknąć, jeśli nie jest to wymagane. |
Ponieważ dla każdej lokalizacji utrzymywana jest oddzielna lista połączona, zajmowane miejsce jest duże. | Ponieważ wszystkie wpisy są umieszczane w tej samej tabeli, zajmowane miejsce jest mniejsze. |
Implementacja tablicy skrótów w C ++
Możemy zaimplementować haszowanie, używając tablic lub połączonych list do programowania tablic haszujących. W C ++ mamy również funkcję zwaną „hash map”, która jest strukturą podobną do tablicy hash, ale każdy wpis jest parą klucz-wartość. W C ++ nazywa się to mapą skrótu lub po prostu mapą. Mapa skrótów w C ++ jest zwykle nieuporządkowana.
Istnieje nagłówek zdefiniowany w Standard Template Library (STL) w C ++, który implementuje funkcjonalność map. Omówiliśmy Mapy STL szczegółowo w naszym samouczku dotyczącym STL.
Poniższa implementacja służy do tworzenia skrótów przy użyciu połączonych list jako struktury danych dla tabeli skrótów. W tej implementacji używamy również „łańcuchów” jako techniki rozwiązywania kolizji.
#include #include using namespace std; class Hashing { int hash_bucket; // No. of buckets // Pointer to an array containing buckets list *hashtable; public: Hashing(int V); // Constructor // inserts a key into hash table void insert_key(int val); // deletes a key from hash table void delete_key(int key); // hash function to map values to key int hashFunction(int x) { return (x % hash_bucket); } void displayHash(); }; Hashing::Hashing(int b) { this->hash_bucket = b; hashtable = new list (hash_bucket); } //insert to hash table void Hashing::insert_key(int key) { int index = hashFunction(key); hashtable(index).push_back(key); } void Hashing::delete_key(int key) { // get the hash index for key int index = hashFunction(key); // find the key in (inex)th list list :: iterator i; for (i = hashtable(index).begin(); i != hashtable(index).end(); i++) { if (*i == key) break; } // if key is found in hash table, remove it if (i != hashtable(index).end()) hashtable(index).erase(i); } // display the hash table void Hashing::displayHash() { for (int i = 0; i ' << x; cout << endl; } } // main program int main() { // array that contains keys to be mapped int hash_array() = {11,12,21, 14, 15}; int n = sizeof(hash_array)/sizeof(hash_array(0)); Hashing h(7); // Number of buckets = 7 //insert the keys into the hash table for (int i = 0; i < n; i++) h.insert_key(hash_array(i)); // display the Hash table cout<<'Hash table created:'< Wynik:
Utworzono tabelę haszującą:
0 -> 21 -> 14
1 -> 15
dwa
3
4 -> 11
5 -> 12
6
Hash table po usunięciu klucza 12:
0 -> 21 -> 14
1 -> 15
dwa
3
4 -> 11
5
6
Dane wyjściowe pokazują utworzoną tabelę skrótów o rozmiarze 7. Używamy łańcucha do rozwiązywania kolizji. Tabelę skrótów wyświetlamy po usunięciu jednego z kluczy.
Zastosowania haszowania
# 1) Weryfikacja haseł: Weryfikacja haseł zwykle odbywa się za pomocą kryptograficznych funkcji skrótu. Po wprowadzeniu hasła system oblicza skrót hasła, a następnie jest wysyłany na serwer w celu weryfikacji. Na serwerze przechowywane są wartości skrótu oryginalnych haseł.
# 2) Struktury danych: Różne struktury danych, takie jak unordered_set i unordered_map w C ++, słowniki w Pythonie lub C #, HashSet i hash map w Javie używają pary klucz-wartość, w której klucze są unikalnymi wartościami. Wartości mogą być takie same dla różnych kluczy. Do implementacji tych struktur danych używane jest haszowanie.
# 3) Podsumowanie wiadomości: To kolejna aplikacja, która używa kryptograficznego skrótu. W podsumowaniu wiadomości obliczamy hash dla wysyłanych i odbieranych danych, a nawet plików i porównujemy je z przechowywanymi wartościami, aby upewnić się, że pliki danych nie są modyfikowane. Najpopularniejszym tutaj algorytmem jest „SHA 256”.
# 4) Działanie kompilatora: Kiedy kompilator kompiluje program, słowa kluczowe dla języka programowania są przechowywane inaczej niż inne identyfikatory. Kompilator używa tablicy skrótów do przechowywania tych słów kluczowych.
# 5) Indeksowanie bazy danych: Tabele skrótów są używane do indeksowania baz danych i struktur danych opartych na dyskach.
# 6) Tablice asocjacyjne: Tablice asocjacyjne to tablice, których indeksy są typu danych innego niż ciągi liczb całkowitych lub inne typy obiektów. Tabele skrótów mogą być używane do implementowania tablic asocjacyjnych.
Wniosek
Hashowanie jest najczęściej używaną strukturą danych, ponieważ operacje wstawiania, usuwania i wyszukiwania wymagają stałego czasu O (1). Haszowanie jest najczęściej realizowane przy użyciu funkcji skrótu, która oblicza unikalną, mniejszą wartość klucza dla dużych wpisów danych. Możemy zaimplementować haszowanie za pomocą tablic i połączonych list.
Jeśli co najmniej jeden wpis danych odpowiada tym samym wartościom kluczy, dochodzi do kolizji. Widzieliśmy różne techniki rozwiązywania kolizji, w tym sondowanie liniowe, łańcuchy itp. Widzieliśmy również implementację haszowania w C ++.
Podsumowując, możemy powiedzieć, że haszowanie jest zdecydowanie najbardziej wydajną strukturą danych w świecie programowania.
=> Poszukaj całej serii szkoleń C ++ tutaj.
rekomendowane lektury
- Jak pisać złożone scenariusze testów logiki biznesowej przy użyciu techniki tabeli decyzyjnej
- Tabela walidacji terenowej (FVT): Technika projektowania testów do walidacji w terenie
- Samouczek QTP nr 15 - Używanie obszaru tekstowego, tabeli i punktów kontrolnych strony w QTP
- MAPY W STL
- Wszystko o routerach: typy routerów, tablice routingu i routing IP
- Top 40 najlepszych pytań i odpowiedzi do wywiadów MySQL (2021 pytań)
- 90 najpopularniejszych pytań i odpowiedzi do wywiadów SQL (NAJNOWSZE)
- Polecenia programów narzędziowych systemu Unix: Which, Man, Find Su, Sudo (część D)