hash table c programs implement hash table
In deze zelfstudie worden C ++ hash-tabellen en hash-kaarten uitgelegd. U leert ook over hash-tabeltoepassingen en implementatie in C ++:
Hashing is een techniek waarmee we een grote hoeveelheid gegevens kunnen mappen naar een kleinere tabel met behulp van een 'hash-functie'.
Met behulp van de hash-techniek kunnen we de gegevens sneller en efficiënter doorzoeken in vergelijking met andere zoektechnieken zoals lineair en binair zoeken.
Laten we de hash-techniek begrijpen met een voorbeeld in deze tutorial.
Lees de Easy C ++ Training Series door.
Wat je leert:
Hashing in C ++
Laten we een voorbeeld nemen van een universiteitsbibliotheek die duizenden boeken herbergt. De boeken zijn gerangschikt volgens onderwerpen, afdelingen, enz. Maar toch zal elke sectie talloze boeken bevatten, waardoor het zoeken naar boeken zeer moeilijk wordt.
Om deze moeilijkheid te overwinnen, kennen we een uniek nummer of unieke sleutel toe aan elk boek, zodat we onmiddellijk de locatie van het boek weten. Dit wordt inderdaad bereikt door hashing.
We gaan verder met ons bibliotheekvoorbeeld, in plaats van elk boek te identificeren op basis van zijn afdeling, onderwerp, sectie, enz. Wat kan resulteren in een zeer lange reeks, berekenen we een unieke gehele waarde of sleutel voor elk boek in de bibliotheek met behulp van een unieke functie en bewaar deze sleutels in een aparte tafel.
De unieke functie die hierboven wordt genoemd, wordt de 'Hash-functie' genoemd en de aparte tabel wordt 'Hash-tabel' genoemd. Een hash-functie wordt gebruikt om de gegeven waarde toe te wijzen aan een bepaalde unieke sleutel in de hash-tabel. Dit resulteert in een snellere toegang tot elementen. Hoe efficiënter de hash-functie is, des te efficiënter zal de toewijzing van elk element aan de unieke sleutel zijn.
Laten we eens kijken naar een hash-functie h (x) die de waarde ' X ' Bij ' x% 10 ”In de array. Voor de gegeven gegevens kunnen we een hashtabel samenstellen met sleutels of hashcodes of hashcodes, zoals weergegeven in het onderstaande diagram.
In het bovenstaande diagram kunnen we zien dat de items in de array met behulp van een hash-functie zijn toegewezen aan hun posities in de hashtabel.
We kunnen dus zeggen dat hashing wordt geïmplementeerd met behulp van twee stappen, zoals hieronder vermeld:
# 1) De waarde wordt geconverteerd naar een unieke sleutel met een geheel getal of hash door een hash-functie te gebruiken. Het wordt gebruikt als een index om het originele element op te slaan, dat in de hashtabel valt.
In het bovenstaande diagram is waarde 1 in de hashtabel de unieke sleutel om element 1 op te slaan uit de gegevensmatrix die wordt weergegeven op de LHS van het diagram.
#twee) Het element uit de gegevensarray wordt opgeslagen in de hashtabel, waar het snel kan worden opgehaald met de hash-sleutel. In het bovenstaande diagram hebben we gezien dat we alle elementen in de hashtabel hebben opgeslagen nadat we hun respectieve locaties hebben berekend met behulp van een hash-functie. We kunnen de volgende uitdrukkingen gebruiken om hash-waarden en index op te halen.
Hash-functie
We hebben al gezegd dat de efficiëntie van mapping afhangt van de efficiëntie van de hash-functie die we gebruiken.
Een hash-functie zou in principe aan de volgende vereisten moeten voldoen:
- Gemakkelijk te berekenen: Een hash-functie moet eenvoudig zijn om de unieke sleutels te berekenen.
- Minder botsing: Wanneer elementen gelijk zijn aan dezelfde sleutelwaarden, treedt er een botsing op. Er moeten zoveel mogelijk botsingen zijn in de hash-functie die wordt gebruikt. Omdat botsingen onvermijdelijk zullen plaatsvinden, moeten we geschikte technieken voor het oplossen van botsingen gebruiken om voor de botsingen te zorgen.
- Uniforme verdeling: De hash-functie moet resulteren in een uniforme verdeling van gegevens over de hashtabel en daardoor clustering voorkomen.
Hash-tabel C ++
Een hash-tabel of een hash-map is een datastructuur waarin verwijzingen naar de elementen van de oorspronkelijke datamatrix worden opgeslagen.
In ons bibliotheekvoorbeeld bevat de hashtabel voor de bibliotheek verwijzingen naar elk van de boeken in de bibliotheek.
Het hebben van items in de hashtabel maakt het gemakkelijker om naar een bepaald element in de array te zoeken.
Zoals we al hebben gezien, gebruikt de hashtabel een hash-functie om de index te berekenen in de reeks buckets of slots waarmee de gewenste waarde kan worden gevonden.
Beschouw een ander voorbeeld met de volgende gegevensmatrix:
Stel dat we een hashtabel van maat 10 hebben, zoals hieronder weergegeven:
Laten we nu de onderstaande hash-functie gebruiken.
Dit komt overeen met Hash_code = Sleutelwaarde% 10
Met behulp van de bovenstaande functie wijzen we de sleutelwaarden toe aan de hashtabellocaties, zoals hieronder wordt weergegeven.
Data item | Hash-functie | Hash_code |
---|---|---|
22 | 22% 10 = 2 | twee |
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 |
Met behulp van de bovenstaande tabel kunnen we de hashtabel als volgt weergeven.
Dus als we toegang moeten hebben tot een element uit de hashtabel, kost het O (1) tijd om de zoekopdracht uit te voeren.
Botsing
We berekenen de hash-code meestal met behulp van de hash-functie, zodat we de sleutelwaarde kunnen toewijzen aan de hash-code in de hash-tabel. Laten we in het bovenstaande voorbeeld van de gegevensmatrix een waarde 12 invoegen. In dat geval is de hash_code voor sleutelwaarde 12 2. (12% 10 = 2).
Maar in de hashtabel hebben we al een toewijzing aan sleutelwaarde 22 voor hash_code 2, zoals hieronder wordt weergegeven:
Zoals hierboven getoond, hebben we dezelfde hash-code voor twee waarden, 12 en 22, d.w.z. 2. Wanneer een of meer sleutelwaarden gelijk zijn aan dezelfde locatie, resulteert dit in een botsing. De hashcodelocatie is dus al bezet door één sleutelwaarde en er is een andere sleutelwaarde die op dezelfde locatie moet worden geplaatst.
verschil tussen qa en qc bij het testen van software
In het geval van hashing, zelfs als we een hashtabel van zeer grote omvang hebben, is er ongetwijfeld een botsing. Dit komt omdat we in het algemeen een kleine unieke waarde voor een grote sleutel vinden, daarom is het heel goed mogelijk dat een of meer waarden op een bepaald moment dezelfde hashcode hebben.
Aangezien een botsing onvermijdelijk is bij hashing, moeten we altijd zoeken naar manieren om de botsing te voorkomen of op te lossen. Er zijn verschillende technieken voor het oplossen van botsingen die we kunnen gebruiken om de botsing tijdens het hashen op te lossen.
Technieken voor het oplossen van botsingen
Hieronder volgen de technieken die we kunnen gebruiken om botsingen in de hashtabel op te lossen.
Afzonderlijke chaining (Open Hashing)
Dit is de meest gebruikelijke techniek voor het oplossen van botsingen. Dit wordt ook wel open hashing genoemd en wordt geïmplementeerd met behulp van een gekoppelde lijst.
beste gratis video-omzetter voor Windows 7
Bij een afzonderlijke kettingtechniek is elk item in de hashtabel een gekoppelde lijst. Wanneer de sleutel overeenkomt met de hashcode, wordt deze ingevoerd in een lijst die overeenkomt met die specifieke hashcode. Dus als twee sleutels dezelfde hash-code hebben, worden beide vermeldingen in de gekoppelde lijst ingevoerd.
Voor het bovenstaande voorbeeld wordt hieronder een aparte ketting weergegeven.
Het bovenstaande diagram staat voor chaining. Hier gebruiken we de mod (%) functie. We zien dat wanneer twee sleutelwaarden gelijk zijn aan dezelfde hashcode, we deze elementen aan die hashcode koppelen met behulp van een gekoppelde lijst.
Als de sleutels uniform zijn verdeeld over de hashtabel, zijn de gemiddelde kosten voor het opzoeken van de specifieke sleutel afhankelijk van het gemiddelde aantal sleutels in die gekoppelde lijst. Zo blijft gescheiden kettingwerking effectief, zelfs als het aantal ingangen dan de slots toeneemt.
Het ergste geval voor afzonderlijke chaining is wanneer alle sleutels overeenkomen met dezelfde hash-code en dus alleen in één gekoppelde lijst worden ingevoegd. Daarom moeten we alle vermeldingen in de hashtabel en de kosten opzoeken die evenredig zijn met het aantal sleutels in de tabel.
Lineair tasten (open adressering / gesloten hash)
Bij open adressering of lineaire tasttechniek worden alle invoerrecords in de hashtabel zelf opgeslagen. Wanneer sleutelwaarde wordt toegewezen aan een hashcode en de positie waarnaar wordt verwezen door de hashcode niet bezet is, wordt de sleutelwaarde op die locatie ingevoegd.
Als de positie al bezet is, wordt met behulp van een sonderende reeks de sleutelwaarde ingevoegd in de volgende positie die niet bezet is in de hashtabel.
Voor lineaire sonderingen kan de hash-functie veranderen zoals hieronder weergegeven:
hash = hash% hashTableSize
hash = (hash + 1)% hashTableSize
hash = (hash + 2)% hashTableSize
hash = (hash + 3)% hashTableSize
We zien dat in het geval van lineaire sondering het interval tussen slots of opeenvolgende sondes constant is, d.w.z. 1.
In het bovenstaande diagram zien we dat in de 0thlocatie voeren we 10 in met behulp van de hash-functie 'hash = hash% hash_tableSize'.
Nu komt element 70 ook overeen met locatie 0 in de hashtabel. Maar die locatie is al bezet. Daarom zullen we met behulp van lineaire sondering de volgende locatie vinden die 1 is. Aangezien deze locatie onbezet is, plaatsen we de sleutel 70 op deze locatie zoals weergegeven met een pijl.
De resulterende hash-tabel wordt hieronder weergegeven.
Lineair sonderen kan lijden onder het probleem van 'Primaire Clustering', waarbij de kans bestaat dat de continue cellen bezet raken en de kans op het inbrengen van een nieuw element wordt verkleind.
Ook als twee elementen dezelfde waarde krijgen bij de eerste hash-functie, zullen beide elementen dezelfde sonde-volgorde volgen.
Kwadratisch onderzoek
Kwadratisch sonderen is hetzelfde als lineair sonderen, met als enige verschil het interval dat wordt gebruikt voor het sonderen. Zoals de naam suggereert, gebruikt deze techniek niet-lineaire of kwadratische afstand om slots te bezetten wanneer een botsing plaatsvindt in plaats van lineaire afstand.
Bij kwadratische sondering wordt het interval tussen de slots berekend door een willekeurige polynoomwaarde toe te voegen aan de reeds gehashte index. Deze techniek vermindert de primaire clustering in aanzienlijke mate, maar verbetert niet bij secundaire clustering.
Dubbel hashen
De dubbele hash-techniek is vergelijkbaar met lineaire sondering. Het enige verschil tussen dubbele hashing en lineaire sondering is dat bij dubbele hash-techniek het interval dat voor sonderen wordt gebruikt, wordt berekend met behulp van twee hashfuncties. Omdat we de hash-functie achter elkaar op de sleutel toepassen, elimineert het zowel primaire clustering als secundaire clustering.
Verschil tussen Chaining (Open Hashing) en Linear Probing (Open Addressing)
Chaining (Open Hashing) | Lineair tasten (open adressering) |
---|---|
Sleutelwaarden kunnen buiten de tabel worden opgeslagen met behulp van een aparte gekoppelde lijst. | Sleutelwaarden mogen alleen in de tabel worden opgeslagen. |
Het aantal elementen in de hashtabel kan groter zijn dan de hashtabel. | Het aantal elementen dat aanwezig is in de hashtabel zal het aantal indices in de hashtabel niet overschrijden. |
Verwijderen is efficiënt in kettingtechniek. | Verwijderen kan omslachtig zijn. Kan worden vermeden indien niet vereist. |
Omdat voor elke locatie een aparte gekoppelde lijst wordt bijgehouden, is de ingenomen ruimte groot. | Omdat alle inzendingen in dezelfde tabel zijn ondergebracht, is de ingenomen ruimte kleiner. |
Implementatie van C ++ hash-tabel
We kunnen hashing implementeren door arrays of gekoppelde lijsten te gebruiken om de hashtabellen te programmeren. In C ++ hebben we ook een functie genaamd 'hash-map', een structuur die lijkt op een hashtabel, maar elk item is een sleutel-waardepaar. In C ++ heet het hash-kaart of gewoon een kaart. Hash-map in C ++ is meestal ongeordend.
Er is een header gedefinieerd in Standard Template Library (STL) van C ++ die de functionaliteit van kaarten implementeert. We hebben gedekt STL-kaarten in detail in onze tutorial over STL.
De volgende implementatie is voor hashen met behulp van de gekoppelde lijsten als een gegevensstructuur voor de hashtabel. We gebruiken in deze implementatie ook 'Chaining' als een techniek voor het oplossen van botsingen.
Uitgang:
Hash-tabel gemaakt:
0 -> 21 -> 14
1 -> 15
twee
3
4 -> 11
5 -> 12
6
Hashtabel na verwijdering van sleutel 12:
0 -> 21 -> 14
1 -> 15
twee
3
4 -> 11
5
6
De uitvoer toont een hashtabel die is gemaakt van grootte 7. We gebruiken chaining om een botsing op te lossen. We tonen de hashtabel na het verwijderen van een van de sleutels.
Toepassingen van hasj
# 1) Verificatie van wachtwoorden: Verificatie van wachtwoorden wordt meestal gedaan met behulp van cryptografische hashfuncties. Wanneer het wachtwoord is ingevoerd, berekent het systeem de hash van het wachtwoord en wordt het ter verificatie naar de server gestuurd. Op de server worden de hash-waarden van de originele wachtwoorden opgeslagen.
# 2) Gegevensstructuren: Verschillende datastructuren zoals unordered_set en unordered_map in C ++, woordenboeken in python of C #, HashSet en hash-map in Java gebruiken allemaal een sleutel / waarde-paar waarin sleutels unieke waarden zijn. De waarden kunnen hetzelfde zijn voor verschillende sleutels. Hashing wordt gebruikt om deze datastructuren te implementeren.
# 3) Berichtensamenvatting: Dit is nog een andere applicatie die een cryptografische hash gebruikt. Bij berichtensamenvattingen berekenen we een hash voor gegevens die worden verzonden en ontvangen of zelfs voor bestanden en vergelijken deze met de opgeslagen waarden om ervoor te zorgen dat er niet met de gegevensbestanden wordt geknoeid. Het meest gebruikte algoritme hier is 'SHA 256'.
# 4) Compiler-bewerking: Wanneer de compiler een programma compileert, worden de sleutelwoorden voor programmeertaal anders opgeslagen dan de andere identificeert. De compiler gebruikt een hashtabel om deze sleutelwoorden op te slaan.
# 5) Database-indexering: Hash-tabellen worden gebruikt voor database-indexering en op schijven gebaseerde datastructuren.
# 6) Associatieve arrays: Associatieve arrays zijn arrays waarvan de indices van een ander gegevenstype zijn dan integer-achtige strings of andere objecttypes. Hash-tabellen kunnen worden gebruikt voor het implementeren van associatieve arrays.
Gevolgtrekking
Hashing is de meest gebruikte datastructuur omdat het constant tijd O (1) nodig heeft voor invoegen, verwijderen en zoeken. Hashing wordt meestal geïmplementeerd door een hash-functie te gebruiken die een unieke kleinere sleutelwaarde berekent voor grote gegevensinvoer. We kunnen hashing implementeren met behulp van arrays en gekoppelde lijsten.
Elke keer dat een of meer gegevensinvoer overeenkomt met dezelfde waarden van sleutels, resulteert dit in een botsing. We hebben verschillende technieken voor het oplossen van botsingen gezien, waaronder lineaire sondering, chaining, enz. We hebben ook de implementatie van hashing in C ++ gezien.
Concluderend kunnen we zeggen dat hashing verreweg de meest efficiënte datastructuur in de programmeerwereld is.
Zoek hier de volledige C ++-trainingsserie.
Aanbevolen literatuur
- Hoe complexe testscenario's voor bedrijfslogica te schrijven met behulp van de beslissingstabeltechniek
- Field Validation Table (FVT): een testontwerptechniek voor veldvalidatie
- QTP Tutorial # 15 - Tekstgebied-, tabel- en paginacontrolepunten gebruiken in QTP
- KAARTEN In STL
- Alles over routers: soorten routers, routeringstabel en IP-routering
- Top 40 beste MySQL interviewvragen en antwoorden (2021 vragen)
- Top 90 SQL-interviewvragen en antwoorden (LAATSTE)
- Unix Utilities Programma's Commando's: Which, Man, Find Su, Sudo (Deel D)