hash table c programs implement hash table
Ovaj vodič objašnjava C ++ tablice heširanja i hash karte. Također ćete naučiti o aplikacijama i implementaciji hash tablica u C ++:
Hashing je tehnika pomoću koje možemo mapirati veliku količinu podataka u manju tablicu pomoću 'hash funkcije'.
Korištenjem tehnike raspršivanja možemo pretraživati podatke brže i učinkovitije u usporedbi s drugim tehnikama pretraživanja poput linearnog i binarnog pretraživanja.
Razumijemo tehniku raspršivanja s primjerom u ovom vodiču.
=> Pročitajte jednostavnu seriju C ++ treninga.
gdje mogu streaming anime besplatno
Što ćete naučiti:
- Hashing u C ++
- Primjena C ++ tablice raspršivanja
- Primjene raspršivanja
- Zaključak
Hashing u C ++
Uzmimo primjer fakultetske knjižnice u kojoj se nalaze tisuće knjiga. Knjige su raspoređene prema temama, odjelima itd. Ali, ipak, svaki će odjeljak imati brojne knjige koje time čine pretragu knjiga vrlo teškom.
Stoga, da bismo prevladali ovu poteškoću, svakoj knjizi dodijelimo jedinstveni broj ili ključ tako da odmah znamo mjesto knjige. To se doista postiže raspršivanjem.
Nastavljajući s primjerom naše knjižnice, umjesto da identificiramo svaku knjigu na temelju njezinog odjela, predmeta, odjeljka itd. Što može rezultirati vrlo dugim nizom, izračunavamo jedinstvenu cijelu vrijednost ili ključ za svaku knjigu u knjižnici koristeći jedinstvenu funkciju i pohranite ove ključeve u zasebnu tablicu.
Gore spomenuta jedinstvena funkcija naziva se 'Hash funkcija', a zasebna tablica naziva se 'Hash tablica'. Hash funkcija koristi se za mapiranje zadane vrijednosti na određeni jedinstveni ključ u tablici raspršivanja. To rezultira bržim pristupom elementima. Što je učinkovitija funkcija raspršivanja, učinkovitije će biti mapiranje svakog elementa u jedinstveni ključ.
Razmotrimo hash funkciju h (x) koja preslikava vrijednost “ x 'U' x% 10 ”U nizu. Za dane podatke možemo stvoriti tablicu raspršivanja koja sadrži ključeve ili hash kodove ili hashove kako je prikazano na donjem dijagramu.
U gornjem dijagramu možemo vidjeti da su unosi u polju preslikani na svoja mjesta u hash tablici pomoću hash funkcije.
Stoga možemo reći da se raspršivanje provodi u dva koraka kako je spomenuto u nastavku:
# 1) Vrijednost se pretvara u jedinstveni cjelobrojni ključ ili hash pomoću hash funkcije. Koristi se kao indeks za pohranu izvornog elementa, koji spada u tablicu raspršivanja.
U gornjem dijagramu, vrijednost 1 u tablici raspršivanja jedinstveni je ključ za pohranu elementa 1 iz niza podataka danih na LHS dijagrama.
#dva) Element iz niza podataka pohranjuje se u tablicu raspršivanja gdje se može brzo dohvatiti pomoću raspršene tipke. U gornjem dijagramu vidjeli smo da smo pohranili sve elemente u hash tablicu nakon izračunavanja njihovih odgovarajućih mjesta pomoću hash funkcije. Sljedeće izraze možemo koristiti za dohvaćanje hash vrijednosti i indeksa.
hash = hash_func(key) index = hash % array_size
Hash funkcija
Već smo spomenuli da učinkovitost mapiranja ovisi o učinkovitosti hash funkcije koju koristimo.
Hash funkcija u osnovi treba ispunjavati sljedeće zahtjeve:
- Jednostavno za izračunavanje: Funkcija raspršivanja trebala bi biti jednostavna za izračunavanje jedinstvenih ključeva.
- Manje sudara: Kada se elementi izjednače s istim ključnim vrijednostima, dolazi do sudara. Trebalo bi biti najmanje sudara što je više moguće u funkciji raspršivanja koja se koristi. Kako će se sudari sigurno dogoditi, moramo se pobrinuti za odgovarajuće tehnike rješavanja sudara kako bismo se pobrinuli za sudare.
- Ujednačena distribucija: Funkcija raspršivanja trebala bi rezultirati jednolikom raspodjelom podataka kroz tablicu raspršivanja i time spriječiti grupiranje.
Hash tablica C ++
Hash tablica ili hash karta je struktura podataka koja pohranjuje pokazivače na elemente izvornog niza podataka.
U našem primjeru knjižnice, hash tablica knjižnice sadržavat će pokazivače na svaku knjigu u knjižnici.
Imajući unose u hash tablici olakšava se traženje određenog elementa u polju.
Kao što je već viđeno, hash tablica koristi hash funkciju za izračunavanje indeksa u niz segmenata ili utora pomoću kojih se može pronaći željena vrijednost.
Razmotrimo još jedan primjer sa sljedećim nizom podataka:
Pretpostavimo da imamo tablicu raspršivanja veličine 10 kako je prikazano dolje:
Sada upotrijebimo hash funkciju navedenu u nastavku.
Hash_code = Key_value % size_of_hash_table
To će se izjednačiti s Hash_code = Vrijednost_ključa% 10
Koristeći gornju funkciju, mapiramo vrijednosti ključeva na mjesta hash tablice, kao što je prikazano u nastavku.
Stavka podataka | Hash funkcija | Hash_code |
---|---|---|
22 | 22% 10 = 2 | dva |
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 | 1 |
Pomoću gornje tablice možemo predstaviti hash tablicu na sljedeći način.
Dakle, kad trebamo pristupiti elementu iz hash tablice, trebat će samo O (1) vremena da pretražimo.
Sudar
Obično izračunavamo hash kod pomoću hash funkcije kako bismo mogli preslikati vrijednost ključa na hash kôd u hash tablici. U gornji primjer niza podataka umetnimo vrijednost 12. U tom će slučaju hash_code za ključnu vrijednost 12 biti 2. (12% 10 = 2).
Ali u hash tablici već imamo mapiranje na ključ / vrijednost 22 za hash_code 2 kao što je prikazano u nastavku:
Kao što je gore prikazano, imamo isti hash kod za dvije vrijednosti, 12 i 22, tj. 2. Kada se jedna ili više ključnih vrijednosti izjednače s istim mjestom, to rezultira sudarom. Prema tome, mjesto hash koda već zauzima jedna vrijednost ključa, a postoji još jedna vrijednost ključa koju treba smjestiti na isto mjesto.
U slučaju raspršivanja, čak i ako imamo tablicu raspršivanja vrlo velike veličine, tada mora doći do sudara. To je zato što uopće pronalazimo malu jedinstvenu vrijednost za veliki ključ, stoga je potpuno moguće da jedna ili više vrijednosti imaju isti hash kôd u bilo kojem trenutku.
S obzirom na to da je sudar neizbježan u raspršivanju, uvijek bismo trebali tražiti načine za sprječavanje ili rješavanje sudara. Postoje razne tehnike rješavanja sudara koje možemo upotrijebiti za rješavanje sudara koji se javljaju tijekom raspršivanja.
Tehnike rješavanja sudara
Slijede tehnike koje možemo upotrijebiti za rješavanje sudara u hash tablici.
Odvojeno ulančavanje (otvoreno raspršivanje)
Ovo je najčešća tehnika rješavanja sudara. To je također poznato kao otvoreno raspršivanje i provodi se pomoću povezanog popisa.
Primjer sortiranja mjehurića c ++
U zasebnoj tehnici ulančavanja, svaki unos u hash tablicu je povezani popis. Kad se ključ podudara s hash kodom, on se unosi na popis koji odgovara tom određenom hash kodu. Dakle, kada dvije tipke imaju isti hash kod, tada se oba unosa unose na povezani popis.
Za gornji primjer, odvojeno ulančavanje predstavljeno je u nastavku.
Gornji dijagram predstavlja ulančavanje. Ovdje koristimo mod (%) funkciju. Vidimo da kada se dvije ključne vrijednosti izjednače s istim hash kodom, tada povezujemo te elemente s tim hash kodom pomoću povezanog popisa.
Ako su ključevi ravnomjerno raspoređeni po tablici raspršivanja, prosječni trošak traženja određenog ključa ovisi o prosječnom broju ključeva na tom povezanom popisu. Stoga odvojeno ulančavanje ostaje na snazi čak i kada se poveća broj unosa nego utora.
Najgori slučaj za odvojeno ulančavanje je kada se svi ključevi izjednačavaju s istim hash kodom i tako se ubacuju samo na jedan povezani popis. Stoga moramo potražiti sve unose u hash tablicu i troškove koji su proporcionalni broju tipki u tablici.
Linearno sondiranje (otvoreno adresiranje / zatvoreno raspršivanje)
U tehnici otvorenog adresiranja ili linearnog sondiranja, svi se unosi pohranjuju u samu tablicu raspršivanja. Kada se ključ-vrijednost preslika na hash kôd i položaj na koji pokazuje hash kôd nije zauzet, tada se vrijednost ključa umetne na to mjesto.
Ako je položaj već zauzet, tada se pomoću sekvence ispitivanja vrijednost ključa ubacuje u sljedeće mjesto koje je nezauzeto u tablici raspršivanja.
Za linearno sondiranje, hash funkcija može se promijeniti kako je prikazano dolje:
hash = hash% hashTableSize
hash = (hash + 1)% hashTableSize
hash = (hash + 2)% hashTableSize
hash = (hash + 3)% hashTableSize
Vidimo da je u slučaju linearnog sondiranja interval između proreza ili uzastopnih sondi konstantan, tj. 1.
Na gornjem dijagramu vidimo da je u 0thmjesto unosimo 10 pomoću hash funkcije “hash = hash% hash_tableSize”.
Sada se element 70 također izjednačava s mjestom 0 u hash tablici. Ali to je mjesto već zauzeto. Stoga ćemo pomoću linearnog sondiranja pronaći sljedeće mjesto koje je 1. Kako je ovo mjesto nezauzeto, na ovo mjesto postavljamo ključ 70 kako je prikazano strelicom.
Dobivena Hash tablica prikazana je u nastavku.
Linearno sondiranje može patiti od problema 'Primarnog grozdenja' u kojem postoji vjerojatnost da će se kontinuirane stanice zauzeti i vjerojatnost umetanja novog elementa smanjiti.
Također ako dva elementa dobiju istu vrijednost na prvoj hash funkciji, tada će oba ova elementa slijediti isti slijed sonde.
Kvadratno sondiranje
Kvadratno sondiranje isto je što i linearno sondiranje, jedina razlika je interval korišten za sondiranje. Kao što i samo ime govori, ova tehnika koristi nelinearnu ili kvadratnu udaljenost za zauzimanje proreza kada se dogodi sudar umjesto linearne udaljenosti.
U kvadratnom sondiranju interval između utora izračunava se dodavanjem proizvoljne polinomske vrijednosti u već raspršeni indeks. Ova tehnika značajno smanjuje primarno grupiranje, ali ne poboljšava sekundarno grupiranje.
Dvostruko raspršivanje
Tehnika dvostrukog raspršivanja slična je linearnom sondiranju. Jedina razlika između dvostrukog raspršivanja i linearnog sondiranja je u tome što se u tehnici dvostrukog raspršivanja interval korišten za ispitivanje izračunava pomoću dvije hash funkcije. Budući da primjenjujemo hash funkciju na ključ jedan za drugim, ona eliminira primarno i sekundarno grupiranje.
Razlika između lančanog (otvoreno raspršivanje) i linearnog ispitivanja (otvoreno adresiranje)
Lanac (otvoreno raspršivanje) | Linearno sondiranje (otvoreno adresiranje) |
---|---|
Vrijednosti ključeva mogu se pohraniti izvan tablice pomoću zasebnog povezanog popisa. | Vrijednosti ključeva trebale bi biti pohranjene samo u tablici. |
Broj elemenata u hash tablici može premašiti veličinu hash tablice. | Broj elemenata prisutnih u hash tablici neće premašiti broj indeksa u hash tablici. |
Delecija je učinkovita u tehnici ulančavanja. | Brisanje može biti glomazno. Može se izbjeći ako nije potrebno. |
Budući da se za svako mjesto održava zasebni povezani popis, zauzeti prostor je velik. | Budući da su svi unosi smješteni u istoj tablici, zauzeto je manje mjesta. |
Primjena C ++ tablice raspršivanja
Heširanje možemo implementirati pomoću nizova ili povezanih popisa za programiranje hash tablica. U C ++ imamo i značajku koja se naziva 'hash map' koja je struktura slična hash tablici, ali svaki je unos par ključ / vrijednost. U C ++-u se zove hash map ili jednostavno karta. Mapa hasha u C ++-u obično je neuređena.
Postoji zaglavlje definirano u Standard Template Library (STL) na C ++ koje implementira funkcionalnost karata. Pokrili smo STL karte detaljno u našem vodiču o STL-u.
Sljedeća je implementacija za raspršivanje pomoću povezanih popisa kao strukture podataka za raspršenu tablicu. U ovoj izvedbi također koristimo 'Chaining' kao tehniku rješavanja sudara.
#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:'< Izlaz:
Izrađena hash tablica:
0 -> 21 -> 14
1 -> 15
dva
3
4 -> 11
5 -> 12
6
Hash tablica nakon brisanja ključa 12:
0 -> 21 -> 14
1 -> 15
dva
3
4 -> 11
5
6
Izlaz prikazuje tablicu raspršivanja koja je kreirana veličine 7. Koristimo ulančavanje za rješavanje sudara. Tablicu raspršivanja prikazujemo nakon brisanja jedne od tipki.
Primjene raspršivanja
# 1) Provjera lozinki: Provjera lozinki obično se vrši pomoću kriptografskih hash funkcija. Kada se unese lozinka, sustav izračunava hash lozinke i zatim se šalje poslužitelju na provjeru. Na poslužitelju se pohranjuju hash vrijednosti izvornih lozinki.
# 2) Strukture podataka: Različite strukture podataka poput unordered_set i unuorder_map u C ++, rječnici u pythonu ili C #, HashSet i hash map u Javi koriste parove ključ / vrijednost u kojima su ključevi jedinstvene vrijednosti. Vrijednosti mogu biti iste za različite ključeve. Hashing se koristi za implementaciju ovih struktura podataka.
# 3) Sažetak poruke: Ovo je još jedna aplikacija koja koristi kriptografski hash. U sažetcima poruka izračunavamo hash za podatke koji se šalju i primaju ili čak datoteke i uspoređujemo ih s pohranjenim vrijednostima kako bismo osigurali da se datoteke podataka ne miješaju. Ovdje je najčešći algoritam 'SHA 256'.
# 4) Rad kompajlera: Kad kompajler kompajlira program, ključne riječi za programski jezik pohranjuju se drugačije od ostalih identificira. Prevoditelj koristi hash tablicu za spremanje ovih ključnih riječi.
# 5) Indeksiranje baze podataka: Hash tablice koriste se za indeksiranje baze podataka i podatkovne strukture temeljene na disku.
# 6) Asocijativni nizovi: Asocijativni nizovi su nizovi čiji su indeksi tipa podataka koji nisu cjelobrojni nizovi ili drugi tipovi objekata. Hash tablice mogu se koristiti za implementaciju asocijativnih nizova.
Zaključak
Hashing je najčešće korištena struktura podataka jer za umetanje, brisanje i pretraživanje treba konstantno vrijeme O (1). Hashing se uglavnom provodi pomoću hash funkcije koja izračunava jedinstvenu manju vrijednost ključa za velike unose podataka. Heširanje možemo implementirati pomoću nizova i povezanih popisa.
Kad god se jedan ili više unosa podataka izjednače s istim vrijednostima ključeva, dolazi do sudara. Vidjeli smo razne tehnike rješavanja sudara, uključujući linearno sondiranje, ulančavanje itd. Također smo vidjeli primjenu raspršivanja u C ++.
Da zaključimo, možemo reći da je raspršivanje daleko najučinkovitija struktura podataka u svijetu programiranja.
pitanja za intervju za ručno testiranje za petogodišnje iskustvo
=> Ovdje potražite cijelu C ++ seriju treninga.
Preporučena literatura
- Kako pisati složeni scenarij ispitivanja poslovne logike pomoću tehnike tablice odlučivanja
- Tablica za provjeru polja (FVT): Tehnika dizajna ispitivanja za provjeru valjanosti polja
- QTP vodič # 15 - Korištenje tekstualnih područja, tablica i stranica u QTP-u
- KARTE U STL-u
- Sve o usmjerivačima: Vrste usmjerivača, tablica usmjeravanja i IP usmjeravanje
- 40 najboljih pitanja i odgovora za intervju za MySQL (2021 pitanje)
- Vrhunskih 90 pitanja i odgovora za intervju za SQL (NAJNOVIJE)
- Naredbe programa Unix Utilities: Which, Man, Find Su, Sudo (Dio D)