Test af hashtabelmodul 8. april 2008
Introduktion
Svært at overskue modulet (intet namespace eller opdeling i header og src ler). Brugt lang tid på at oversætte modulet. Masser af todos, memory leaks etc. Baseret på vector-modulet, der heller ikke oversatte. Meget omfattende refactoring. Konklusion: Skriv modulet fra bunden.
Hashtabel Tabeludvidelse Hashfunktion Opbevaring af hashværdi Kompleksitet Anvendelse af bridge pattern. Få datastrukturer. Opdeling i header og src ler og anvendelse af namespace. Inkludering af unittest i hvert modul.
Hashtabel Tabeludvidelse Hashfunktion Opbevaring af hashværdi Kompleksitet Hashtabel std::list Bucket 1 Bucket 2 Bucket 3 0 1 1 0 0 1 std::vector n nøgler hashes til m slots i tabellen. Minimere index-range. Elementer med kolliderende hashværdier placeres i buckets. Empty slot Used slot m slots Sentinel Hver bucket højst α = n m elementer (load-factor). Simpelt at understøtte it++ operation.
Hashtabel Tabeludvidelse Hashfunktion Opbevaring af hashværdi Kompleksitet Tabeludvidelse Når load-factor > 5 fordobles kapaciteten. Når load-factor < 2 halveres kapacitet. Genbrug hashværdi, når elementer yttes (beregning af nye index). Under ytning deallokeres/allokeres elementer! Allokering/deallokering administeres af std::vector, std::list.
Hashtabel Tabeludvidelse Hashfunktion Opbevaring af hashværdi Kompleksitet Hashfunktion En god hashfunktion opfylder Simple Uniform Hashing (lige fordeling af nøgler). Universal hashing sikrer denne egenskab. En universal klasse af hashfunktioner er givet ved: H p,m = {h a,b : a Z p and b Z p} hvor p > m der giver p(p 1) hashfunktioner i H p,m. Pr{h a,b (k) = h a,b (l)} 1. m Universal hashing på heltal men ikke strenge. Hashfunktionen skiftes ikke.
Hashtabel Tabeludvidelse Hashfunktion Opbevaring af hashværdi Kompleksitet Opbevaring af hashværdi Et index i tabellen bestemmes ved: index = hash_value MOD capacity Når tabellen udvides/indskrænkes, skal de nye index bestemmes. Gemmes hashværdierne, er det kun MOD, der skal udregnes.
Hashtabel Tabeludvidelse Hashfunktion Opbevaring af hashværdi Kompleksitet Kompleksitet INSERT(v), DELETE(it) tager O(1) tid (dobbelthægtede liste). Antag for tabellen at n = O(m) hvor n er elementer og m er slots i tabellen og load-factoren er givet ved α = n m. SEARCH er proportional med α. Da vi har antaget at n = O(m), fås: O(m) m Forudsætter Simple Uniform Hashing! = O(1).
Multiset og equal_range (1) Multiset og equal_range (2) Skift hashfunktion i forbindelse med udvidelse og sammentrækning. Et element består af: pair<pair<k, V>, pair<bool, hash_value> > Opret en elementklasse (node) i stedet. Udvid med dynamisk hashing i stedet og sammenlign ydelse. Slå opbevaring af hashværdi fra/til (plads contra hastighed). Implementer multiset.
Multiset og equal_range (1) Multiset og equal_range (2) Multiset og equal_range (1) K1 K1 K2 K3 K1 K1 K3 Sorteret bucket. equal_range på bucket.
Multiset og equal_range (1) Multiset og equal_range (2) Multiset og equal_range (2) Tilføj liste. K1 K1 K3 equal_range K1 K2 K1 på listen. K3
900 800 Efficiency of set operations:(cphstl::unordered s et::insert(v) n std::set::insert(v)), integer std::set<int>::insert(v) cphstl::unordered s et<int>::insert(v) Execution time per element [in nanoseconds] 700 600 500 400 300 200 100 0 1e+06 1e+07 n
400 350 Efficiency of set operations:(cphstl::unordered s et::find(e) n std::set::find(e)), integer cphstl::unordered s et<int>::find(e) std::set<int>::find(e) Execution time per element [in nanoseconds] 300 250 200 150 100 50 0 1e+06 1e+07 n
Har ikke nået linear hashing og universal hashfunktioner da refactoring har været meget omfattende. Har kostet blod, sved og tårer at implementere iteratorer (it++ operation). Givet praktisk erfaring med anvendelse af design patterns (bridge, iterator). Nuværende modul er forhåbentlig væsentligt lettere at udvide og overskue. God ydelse.