hash table c programs implement hash table
Denna handledning förklarar C ++ Hash-tabeller och Hash-kartor. Du kommer också att lära dig applikationer och implementering av Hash-tabeller i C ++:
Hashing är en teknik där vi kan kartlägga en stor mängd data till en mindre tabell med en ”hash-funktion”.
Med hjälp av hashtekniken kan vi söka i data snabbare och mer effektivt jämfört med andra söktekniker som linjär och binär sökning.
Låt oss förstå hashingstekniken med ett exempel i denna handledning.
=> Läs igenom Easy C ++ Training Series.
Vad du kommer att lära dig:
Hashing In C ++
Låt oss ta ett exempel på ett högskolebibliotek som rymmer tusentals böcker. Böckerna är ordnade efter ämnen, avdelningar etc. Men ändå kommer varje avsnitt att ha många böcker som därmed gör sökning efter böcker mycket svårt.
För att övervinna denna svårighet tilldelar vi alltså ett unikt nummer eller nyckel till varje bok så att vi omedelbart känner till bokens plats. Detta uppnås verkligen genom hashing.
Fortsätter med vårt biblioteksexempel, istället för att identifiera varje bok baserat på dess avdelning, ämne, avsnitt etc. som kan resultera i en mycket lång sträng beräknar vi ett unikt heltalsvärde eller nyckel för varje bok i biblioteket med en unik funktion och förvara dessa nycklar i en separat tabell.
Den unika funktionen som nämns ovan kallas 'Hash-funktionen' och den separata tabellen kallas 'Hash-tabell'. En hash-funktion används för att mappa det angivna värdet till en viss unik nyckel i Hash-tabellen. Detta resulterar i snabbare åtkomst till element. Ju effektivare hashing-funktionen är, desto effektivare blir kartläggningen av varje element till den unika nyckeln.
Låt oss överväga en hash-funktion h (x) som kartlägger värdet “ x ”Vid“ x% 10 ”I matrisen. För den givna informationen kan vi konstruera en hash-tabell som innehåller nycklar eller hash-koder eller hash som visas i nedanstående diagram.
I ovanstående diagram kan vi se att posterna i matrisen mappas till sina positioner i hashtabellen med en hash-funktion.
Således kan vi säga att hashing implementeras med två steg som nämns nedan:
# 1) Värdet konverteras till en unik heltalsknapp eller hash med en hash-funktion. Det används som ett index för att lagra originalelementet, som faller in i hashtabellen.
I ovanstående diagram är värde 1 i hashtabellen den unika nyckeln för att lagra element 1 från den dataarray som anges på LHS i diagrammet.
#två) Elementet från dataarrayen lagras i hashtabellen där det snabbt kan hämtas med hashknappen. I ovanstående diagram såg vi att vi har lagrat alla element i hashtabellen efter att ha beräknat sina respektive platser med en hash-funktion. Vi kan använda följande uttryck för att hämta hash-värden och indexera.
hash = hash_func(key) index = hash % array_size
Hash-funktion
Vi har redan nämnt att kartläggningens effektivitet beror på effektiviteten hos hashfunktionen som vi använder.
En hash-funktion bör i grunden uppfylla följande krav:
- Lätt att beräkna: En hash-funktion, bör vara lätt att beräkna de unika tangenterna.
- Mindre kollision: När element motsvarar samma nyckelvärden inträffar en kollision. Det bör finnas minimikollisioner så långt som möjligt i hashfunktionen som används. Eftersom kollisioner kommer att inträffa måste vi använda lämpliga kollisionsupplösningstekniker för att ta hand om kollisionerna.
- Jämn fördelning: Hash-funktionen bör resultera i en enhetlig fördelning av data över hashtabellen och därigenom förhindra kluster.
Hash-tabell C ++
Hashtabell eller en hashkarta är en datastruktur som lagrar pekare till elementen i den ursprungliga dataarrayen.
I vårt biblioteksexempel kommer hashtabellen för biblioteket att innehålla pekare till var och en av böckerna i biblioteket.
Att ha poster i hashtabellen gör det lättare att söka efter ett visst element i matrisen.
Som redan sett använder hash-tabellen en hash-funktion för att beräkna indexet i matrisen med hinkar eller slots som använder det önskade värdet.
Tänk på ett annat exempel med följande dataarray:
Antag att vi har en hashtabell av storlek 10 enligt nedan:
Låt oss nu använda hash-funktionen nedan.
Hash_code = Key_value % size_of_hash_table
Detta motsvarar Hash_code = Key_value% 10
World of Warcraft privata pvp-server
Med hjälp av ovanstående funktion kartlägger vi nyckelvärdena till hashtabellplatserna enligt nedan.
Dataobjekt | Hash-funktion | Hash-kod |
---|---|---|
22 | 22% 10 = 2 | två |
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 | ett |
Med hjälp av ovanstående tabell kan vi representera hashtabellen enligt följande.
Så när vi behöver komma åt ett element från hashtabellen tar det bara O (1) tid att göra sökningen.
Kollision
Vi beräknar vanligtvis hash-koden med hash-funktionen så att vi kan mappa nyckelvärdet till hash-koden i hashtabellen. I ovanstående exempel på dataarrayen, låt oss infoga ett värde 12. I så fall kommer hash_code för nyckelvärde 12 att vara 2. (12% 10 = 2).
Men i hashtabellen har vi redan en mappning till nyckel-värde 22 för hash_code 2 som visas nedan:
Som visas ovan har vi samma hashkod för två värden, 12 och 22, dvs. 2. När ett eller flera nyckelvärden motsvarar samma plats, resulterar det i en kollision. Således upptas hashkodsplatsen redan av ett nyckelvärde och det finns ett annat nyckelvärde som måste placeras på samma plats.
I fallet med hashing, även om vi har en hashbord av mycket stor storlek, är en kollision sannolikt där. Detta beror på att vi i allmänhet hittar ett litet unikt värde för en stor nyckel, därför är det helt möjligt för ett eller flera värden att ha samma hashkod vid varje given tidpunkt.
Med tanke på att en kollision är oundviklig vid hashing, bör vi alltid leta efter sätt att förhindra eller lösa kollisionen. Det finns olika kollisionsupplösningstekniker som vi kan använda för att lösa kollisionen som uppstår under hashing.
Kollisionsupplösningstekniker
Följande är de tekniker som vi kan använda för att lösa kollision i hashtabellen.
Separat kedja (Open Hashing)
Detta är den vanligaste tekniken för kollisionsupplösning. Detta kallas också öppen hashing och implementeras med hjälp av en länkad lista.
I separat kedjeteknik är varje post i hashtabellen en länkad lista. När nyckeln matchar hashkoden matas den in i en lista som motsvarar den specifika hashkoden. Således när två tangenter har samma hash-kod matas båda posterna in i den länkade listan.
För ovanstående exempel representeras separat kedja nedan.
Ovanstående diagram representerar kedjning. Här använder vi mod (%) -funktionen. Vi ser att när två nyckelvärden motsvarar samma hash-kod, länkar vi dessa element till den hash-koden med hjälp av en länkad lista.
Om nycklarna är jämnt fördelade över hashtabellen beror den genomsnittliga kostnaden för att leta efter den specifika nyckeln på det genomsnittliga antalet nycklar i den länkade listan. Sålunda förblir separat kedja effektiv även när det ökar antalet inmatningar än spåren.
Det värsta fallet för separat kedja är när alla nycklar motsvarar samma hash-kod och därmed bara infogas i en länkad lista. Därför måste vi leta upp alla poster i hashtabellen och kostnaden som är proportionell mot antalet tangenter i tabellen.
Linjär sondering (öppen adressering / stängd hash)
I öppen adressering eller linjär sonderingsteknik lagras alla postposter i själva hashtabellen. När nyckelvärdet mappas till en hashkod och den position som pekas på med hashkod är ledig, infogas nyckelvärdet på den platsen.
Om positionen redan är upptagen infogas nyckelvärdet i nästa position som inte är upptagen i hashtabellen med hjälp av en sonderingssekvens.
För linjär sondering kan hashfunktionen ändras enligt nedan:
hash = hash% hashTableSize
hash = (hash + 1)% hashTableSize
hash = (hash + 2)% hashTableSize
hash = (hash + 3)% hashTableSize
Vi ser att vid linjär sondering är intervallet mellan slitsar eller på varandra följande sonder konstant, dvs. 1.
I ovanstående diagram ser vi att i 0thplats vi anger 10 med hash-funktionen “hash = hash% hash_tableSize”.
Nu motsvarar elementet 70 också plats 0 i hashtabellen. Men den platsen är redan upptagen. Därför använder vi linjär sondering nästa plats som är 1. Eftersom denna plats är ledig placerar vi nyckeln 70 på den här platsen som visas med en pil.
Den resulterande Hash-tabellen visas nedan.
Linjär sondering kan drabbas av problemet med 'Primary Clustering' där det finns en chans att de kontinuerliga cellerna kan upptas och sannolikheten för att infoga ett nytt element minskar.
Även om två element får samma värde vid den första hashfunktionen, kommer båda dessa element att följa samma sondföljd.
Kvadratisk sondering
Kvadratisk sondering är densamma som linjär sondering med den enda skillnaden som är intervallet som används för sondering. Som namnet antyder använder denna teknik icke-linjärt eller kvadratiskt avstånd för att uppta slitsar när en kollision inträffar istället för linjärt avstånd.
I kvadratisk sondering beräknas intervallet mellan slitsarna genom att lägga till ett godtyckligt polynomvärde till det redan hashade indexet. Denna teknik minskar primärt kluster i betydande utsträckning men förbättras inte vid sekundärt kluster.
Dubbel hasning
Den dubbla hashtekniken liknar linjär sondering. Den enda skillnaden mellan dubbel hasning och linjär sondering är att vid dubbel hasningsteknik intervallet som används för sondering beräknas med två hashfunktioner. Eftersom vi tillämpar hashfunktionen på nyckeln efter varandra, eliminerar den såväl primärt kluster som sekundärt kluster.
Skillnaden mellan kedja (öppen hash) och linjär sondering (öppen adressering)
Kedjning (öppen hash) | Linjär sondering (öppen adressering) |
---|---|
Nyckelvärden kan lagras utanför tabellen med en separat länkad lista. | Nyckelvärden bör endast sparas i tabellen. |
Antalet element i hashtabellen kan överstiga storleken på hashtabellen. | Antalet element som finns i hashtabellen kommer inte att överstiga antalet index i hashtabellen. |
Radering är effektiv i kedjeteknik. | Radering kan vara besvärligt. Kan undvikas om det inte krävs. |
Eftersom en separat länkad lista upprätthålls för varje plats är utrymmet stort. | Eftersom alla poster är placerade i samma tabell är det utrymme som tas mindre. |
C ++ Hash Tabell Implementering
Vi kan implementera hashing genom att använda arrays eller länkade listor för att programmera hashtabellerna. I C ++ har vi också en funktion som kallas 'hash-karta' som är en struktur som liknar en hash-tabell men varje post är ett nyckel-värdepar. I C ++ kallas den hashkarta eller helt enkelt en karta. Hash-karta i C ++ är vanligtvis inte ordnad.
Det finns ett sidhuvud definierat i Standard Template Library (STL) av C ++ som implementerar kartans funktionalitet. Vi har täckt STL-kartor i detalj i vår handledning om STL.
Följande implementering är för hashing med de länkade listorna som datastruktur för hash-tabellen. Vi använder också 'Kedjning' som en teknik för kollisionsupplösning i denna implementering.
#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:'< Produktion:
Hash-tabell skapad:
0 -> 21 -> 14
1 -> 15
två
3
4 -> 11
5 -> 12
6
Hash-tabell efter radering av nyckel 12:
0 -> 21 -> 14
1 -> 15
två
3
4 -> 11
5
6
Utgången visar en hash-tabell som är skapad av storlek 7. Vi använder kedjning för att lösa kollision. Vi visar hashtabellen efter att ha tagit bort en av tangenterna.
Tillämpningar av Hashing
# 1) Verifiering av lösenord: Verifiering av lösenord görs vanligtvis med kryptografiska hashfunktioner. När lösenordet matas in beräknar systemet lösenordets hash och skickas sedan till servern för verifiering. På servern lagras hashvärdena för de ursprungliga lösenorden.
# 2) Datastrukturer: Olika datastrukturer som unordered_set och unordered_map i C ++, ordböcker i python eller C #, HashSet och hash-karta i Java använder alla nyckel-värdepar där nycklar är unika värden. Värdena kan vara desamma för olika tangenter. Hashing används för att implementera dessa datastrukturer.
# 3) Message Digest: Detta är ännu en applikation som använder en kryptografisk hash. I meddelandeklyftningar beräknar vi en hash för att data skickas och tas emot eller till och med filer och jämför dem med de lagrade värdena för att säkerställa att datafilerna inte manipuleras med. Den vanligaste algoritmen här är “SHA 256”.
# 4) Compilerdrift: När kompilatorn kompilerar ett program lagras nyckelorden för programmeringsspråk annorlunda än de andra identifierarna. Kompilatorn använder en hash-tabell för att lagra dessa nyckelord.
# 5) Databasindexering: Hash-tabeller används för databasindexering och diskbaserade datastrukturer.
# 6) Associerande matriser: Associerande matriser är matriser vars index har en annan datatyp än heltal-liknande strängar eller andra objekttyper. Hash-tabeller kan användas för att implementera associerande matriser.
Slutsats
Hashing är den mest använda datastrukturen eftersom det tar konstant tid O (1) för insättning, radering och sökning. Hashing implementeras mestadels genom att använda en hash-funktion som beräknar ett unikt mindre nyckelvärde för stora datainmatningar. Vi kan implementera hashing med hjälp av arrays och länkade listor.
När en eller flera datainmatningar motsvarar samma nyckelvärden, resulterar det i en kollision. Vi har sett olika kollisionsupplösningstekniker inklusive linjär sondering, kedjning etc. Vi har också sett implementeringen av hashing i C ++.
Avslutningsvis kan vi säga att hashing är den absolut effektivaste datastrukturen i programmeringsvärlden.
=> Leta efter hela C ++ träningsserien här.
Rekommenderad läsning
- Hur man skriver komplexa affärslogiska testscenarier med hjälp av beslutstabellsteknik
- Fältvalideringstabell (FVT): En testdesignteknik för fältvalidering
- QTP-handledning # 15 - Använda textområde, tabell och sidkontrollpunkter i QTP
- KARTOR I STL
- Allt om routrar: Typer av routrar, Routing Table och IP Routing
- Topp 40 bästa MySQL-intervjufrågor och svar (2021 frågor)
- Topp 90 SQL-intervjufrågor och svar (LATEST)
- Unix Utilities-program Kommandon: Vilken, Man, Find Su, Sudo (Del D)