Prezentace se nahrává, počkejte prosím

Prezentace se nahrává, počkejte prosím

Datové struktury a algoritmy Část 11 Rozptylování - Hashing Petr Felkel.

Podobné prezentace


Prezentace na téma: "Datové struktury a algoritmy Část 11 Rozptylování - Hashing Petr Felkel."— Transkript prezentace:

1 Datové struktury a algoritmy Část 11 Rozptylování - Hashing Petr Felkel

2 2 / 57 DSA Slovník - Dictionary Řada aplikací potřebuje dynamickou množinu s operacemi: Search, Insert, Delete = slovník Př. Tabulka symbolů překladače identifikátortypadresa sumaint 0xFFFFDC

3 3 / 57 DSA Dictionary Many applications need dynamic set with operations: Search, Insert, Delete = dictionary Ex. Compiler symbol table identifiertypeaddress sumint 0xFFFFDC

4 4 / 57 DSA Vyhledávání Porovnáváním klíčů  (log n) klíč prvku = hledaný klíč např. sekvenční vyhledávání,BVS,... Indexováním klíčem (přímý přístup)  (1) klíč je přímo indexem rozsah klíčů ~ rozsahu indexů Rozptylováním průměrně  (1)! výpočtem adresy z hodnoty klíče

5 5 / 57 DSA Searching Comparing search keys  (log n) search key with keys in items e.g. sequential search,BST,... Key-indexed search (direct access)  (1) use key value directly as array index key range ~ table indices Hashing expected  (1)! transform keys into a table address

6 6 / 57 DSA Rozptylování - Hashing = kompromis mezi rychlostí a spotřebou paměti ∞ času - sekvenční vyhledávání ∞ paměti - přímý přístup (indexování klíčem) velikost tabulky reguluje čas vyhledání

7 7 / 57 DSA Hashing = time-space tradeoff ∞ time - sequential search ∞ space - key-indexed search (direct access) balance by adjusting hash-table size

8 8 / 57 DSA Rozptylování - Hashing Konstantní očekávaný čas pro vyhledání a vkládání (search and insert) !!! Něco za něco: čas provádění ~ délce klíče není vhodné pro operace výběru a řazení (select and sort)

9 9 / 57 DSA Hashing Constant expected time for search and insert but running time does depend on the length of the key not efficient for select and sort

10 10 / 57 DSA Rozptylování Dvě fáze 1. Výpočet rozptylovací funkce h(k) 2. Vyřešení kolizí h(31)..... kolize - index 1 již obsazen klíče M-1 h(2) h(10) h(21) h(k)h(k) 31 h(31)?

11 11 / 57 DSA Hashing Two steps 1. Computation of the hash function h(k) 2. Handling of collisions h(31)..... collision - index 1 already used klíče M-1 h(2) h(10) h(21) h(k)h(k) 31 h(31)?

12 12 / 57 DSA 1. Výpočet rozptylovací funkce h(k) Computation of the hash function h(k)

13 13 / 57 DSA Rozptylovací funkce h(k) Zobrazuje množinu klíčů K do intervalu adres A =, obvykle |K| >> |A| Synonyma: k 1  k 2, h(k 1 ) = h(k 2 ) = kolize

14 14 / 57 DSA Hash function h(k) Transforms the search key into a table address set of keys K table addresses A , usually A  |K| >> |A| Synonyms: k 1  k 2, h(k 1 ) = h(k 2 ) = collision

15 15 / 57 DSA Rozptylovací funkce h(k) Je silně závislá na vlastnostech klíčů a jejich reprezentaci v paměti Ideálně: výpočetně co nejjednodušší (rychlá) aproximuje náhodnou funkci využije rovnoměrně adresní prostor generuje minimum kolizí proto: využívá všechny složky klíče

16 16 / 57 DSA Hash function h(k) Heavily depends on the key properties and on the representation of the keys Ideally: computationally as simple as possible (fast) approximates a random function uses the address space regularly generates minimum of collisions therefore: uses all key parts

17 17 / 57 DSA Rozptylovací funkce h(k)-příklady Hash functions h(k) - examples Pro reálná čísla for real numbers multiplikativní: h(k,M) = round( k * M ) (neoddělí shluky blízkých čísel) (does not separate clusters of similar numbers) M = velikost tabulky

18 18 / 57 DSA Rozptylovací funkce h(k)-příklady Pro celá čísla (w-bitová) - for w-bit integers multiplikativní: (kde M je prvočíslo-prime) h(k,M) = round( k /2 w * M ) modulární: h(k,M) = k % M kombinovaná (combined): h(k,M) = round( c * k ) % M, c  h(k,M) = (int)( * (float) k ) % M h(k,M) = (16161 * (unsigned) k) % M

19 19 / 57 DSA Rychlá, silně závislá na reprezentaci klíčů (Fast, heavily dependent on the representation of keys in memory): h(k) = k & (M-1) pro M = 2 x (není prvočíslo), a & = bitový součin (M not prime, & = bit-wise AND) Rozptylovací funkce h(k)-příklady Hash functions h(k) - examples

20 20 / 57 DSA Rozptylovací funkce h(k)-příklady Pro řetězce (for strings): int hash( char *k, int M ) { int h = 0, a = 127; for( ; *k != 0; k++ ) h = ( a * h + *k ) % M; return h; } // Hornerovo schéma: k 2 * a 2 + k 1 *a 1 + k 0 * a 0 = ((k 2 * a) + k 1 )*a + k 0

21 21 / 57 DSA Rozptylovací funkce h(k)-příklady Pro řetězce:(pseudo-) randomizovaná int hash( char *k, int M ) { int h = 0, a = 31415; b = 27183; for( ; *k != 0; k++, a = a*b % (M-1) ) h = ( a * h + *k ) % M; return h; } // Univerzální rozptylovací fce kolize s pravděpodobností 1/M odlišná náhodná konstanta pro různé pozice v řetězci

22 22 / 57 DSA Hash functions h(k) - examples For strings:(pseudo-) randomized int hash( char *k, int M ) { int h = 0, a = 31415; b = 27183; for( ; *k != 0; k++, a = a*b % (M-1) ) h = ( a * h + *k ) % M; return h; } // Universal hashing function chance of collisions between distinct keys exactly 1/M different random constant for different string positions

23 23 / 57 DSA Rozptylovací funkce h(k)-chyba funkce vrací stejnou hodnotu chyba v konverzi funguje, ale vrací blízké adresy proto generuje hodně kolizí => aplikace je extrémně pomalá

24 24 / 57 DSA Hash functions h(k) - performance bug always to return the same value conversion did not take place properly generates many collisions program is likely to run correctly, but to be extremely slow

25 25 / 57 DSA 2. Vyřešení kolizí Handling of collisions

26 26 / 57 DSA a) Zřetězené rozptylování 1/5 Separate chainimg h(k) = k mod 3 posloupnost (sequence) : 1, 5, 21, 10, \21\75\ linkheads seznamy synonym 10

27 27 / 57 DSA a) Zřetězené rozptylování 2/5 private: link* heads; int N,M; [Sedgewick] public: ST( int maxN ) // initialization { N=0; M = maxN / 5; // No.nodes,table size heads = new link[M];// table with pointers for( int i = 0; i < M; i++ ) heads[i] = null; }...

28 28 / 57 DSA a) Zřetězené rozptylování 3/5 Item search( Key k ) {return searchList( heads[ hash(k, M)], k );} void insert( Item item ) { int i = hash( item.key(), M ); heads[i] = new node( item, heads[i] ); N++; }

29 29 / 57 DSA a) Zřetězené rozptylování 4/5 Řetěz synonym má ideálně délku  =n/m,  >1 (n = počet prvků, m = velikost tabulky, m

30 30 / 57 DSA a) Zřetězené rozptylování 5/5 Praxe: volit m = n/5 až n/10 =>  = 10 prvků / řetěz vyplatí se hledání sekvenčně neplýtvá nepoužitými ukazateli Shrnutí: + nemusíme znát n předem - potřebuje dynamické přidělování paměti - potřebuje paměť na ukazatele a na tabulku[m]

31 31 / 57 DSA b) Otevřené rozptylování (open-addressing hashing) Znám předem počet prvků (odhad) nechci ukazatele (v prvcích ani tabulku) => posloupnost do pole Podle tvaru hashovací funkce h(k) při kolizi 1. linear probing 2. double hashing

32 32 / 57 DSA b) Otevřené rozptylování h(k) = k mod 5 posloupnost: 1, 5, 21, 10, 7 kolize - 1 blokuje 1. linear probing 2. double hashing Pozn.: 1 a 21 jsou synonyma často ale blokuje nesynonymum

33 33 / 57 DSA Probe = určení, zda pozice v tabulce obsahuje klíč shodný s hledaným klíčem search hit = klíč nalezen search miss = pozice prázdná, klíč nenalezen jinak= na pozici je jiný klíč, hledej dál

34 34 / 57 DSA Probe = determining, whether or not a given table position holds an item with a key equal to the search key search hit = key matches search miss = the table position is empty otherwise= the table position contains an item with a different key, so probe the the table position with a next higher index

35 b) Otevřené rozptylování (open-addressing hashing) b1) Linear probing

36 36 / 57 DSA b1) Linear probing h(k) = [(k mod 5) + i ] mod 5 = (k + i) mod 5 posloupnost: 1, 5, 21, 10, 7 kolize - 1 blokuje vlož o pozici dál (i++ => i = 1) insert one position ahead

37 37 / 57 DSA b1) Linear probing h(k) = (k + i) mod 5 posloupnost: 1, 5, 21, 10, 7 1. kolize - 5 blokuje - vlož dál 2. kolize - 1 blokuje - vlož dál 3. kolize - 21 blokuje - vlož dál vloženo o 3 pozice dál (i = 3) collision - position blocked - i++ finally inserted 3 indexes ahead

38 38 / 57 DSA b1) Linear probing h(k) = (k + i) mod 5 posloupnost: 1, 5, 21, 10, 7 1. kolize - vlož dál (i++) 2. kolize - vlož dál (i++) vlož o 2 pozice dál (i = 2)

39 39 / 57 DSA b1) Linear probing h(k) = (k + i) mod 5 posloupnost: 1, 5, 21, 10, i = 0 i = 1 i = 3 i = 2

40 40 / 57 DSA b1) Linear probing private: Item *st; int N,M; [Sedgewick] Item nullItem; public: ST( int maxN ) // initialization { N=0; M = 2*maxN; // load_factor < 1/2 st = new Item[M]; for( int i = 0; i < M; i++ ) st[i] = nullItem; }...

41 41 / 57 DSA b1) Linear probing void insert( Item item ) { int i = hash( item.key(), M ); while( !st[i].null() ) i = (i+1) % M; // Linear probing st[i] = item; N++; }

42 42 / 57 DSA b1) Linear probing Item search( Key k ) { int i = hash( k, M ); while( !st[i].null() ) { // zarážka if( k == st[i].key() ) return st[i]; else i = (i+1) % M; // Linear probing } return nullItem; }

43 b) Otevřené rozptylování (open-addressing hashing) b2) Double hashing

44 44 / 57 DSA b2) Double hashing h(k) = k mod 5 posloupnost: 1, 5, 21, 10, 7 kolize - 1 blokuje (collision-blocks) 1. linear probing 2. double hashing

45 45 / 57 DSA b2) Double hashing h(k) = [(k mod 5) + i.h 2 (k) ] mod 5, h(k) = (k + i.3) mod 5 posloupnost: 1, 5, 21, 10, 7 kolize - 1 blokuje vlož o 3 pozice dál (i++ => i = 1) stačí prvočíslo  m prime number  m

46 46 / 57 DSA b2) Double hashing h(k) = (k + i.3) mod 5 posloupnost: 1, 5, 21, 10, 7 1. kolize - 5 blokuje - vlož dál vlož o 3 pozice dál (i = 1)

47 47 / 57 DSA b2) Double hashing h(k) = (k + i.3) mod 5 posloupnost: 1, 5, 21, 10, 7 i =

48 48 / 57 DSA b2) Double hashing i = 0 i = h(k) = (k + i.3) mod 5 posloupnost: 1, 5, 21, 10, 7

49 49 / 57 DSA Double hashing x Linear probing h(k) = (k + i.3) mod 5 h(k) = (k + i) mod 5 i = 0 i = i = 0 i = 1 i = 3 ! i = 2 vnořené sekvence (mixed probe sequences) dlouhé shluky (long clusters)

50 50 / 57 DSA b2) Double hashing void insert( Item item ) { Key k = item.key(); int i = hash( v, M ), j = hashTwo( v, M ); while( !st[i].null() ) i = (i+j) % M; // Double Hashing st[i] = item; N++; }

51 51 / 57 DSA b2) Double hashing Item search( Key k ) { int i = hash( k, M ), j = hashTwo( v, M ); while( !st[i].null() ) { if( k == st[i].key() ) return st[i]; else i = (i+j) % M; // Double Hashing } return nullItem; }

52 52 / 57 DSA Linear-probing Item Removal // do not leave the hole - it can break a cluster void remove( Item item ) { int i = hash( v, M ), j; while( !st[i].null() ) // find item to remove if( item.key() == st[i].key() ) break; else i = (i+1) % M; if( st[i].null() ) return; // not found st[i] = nullItem; N--; // delete, reinsert for( j = i+1; !st[j].null(); (j+1) % M, N--) { Item v = st[j]; st[j] = nullItem; insert(v); } }

53 53 / 57 DSA Double-hashing Item Removal // Double Hashing - overlapping search sequences // - fill up the hole by sentinel // - skipped by search, replaced by insert void remove( Item item ) { int i = hash( v, M ), j = hashTwo( v, M ); while( !st[i].null() ) // find item to remove if( item.key() == st[i].key() ) break; else i = (i+j) % M; if( st[i].null() ) return; // not found st[i] = sentinelItem; N--; // delete }

54 54 / 57 DSA b) Otevřené rozptylování (open-addressing hashing)  = zaplnění tabulky (load factor of the table)  = n/m,   0,1  n = počet prvků (number of items in the table) m = velikost tabulky, m>n (table size)

55 55 / 57 DSA b) Otevřené rozptylování (open-addressing hashing) Average number of probes [Sedgewick] Linear probing: Search hits 0.5 ( / (1 -  ) ) Search misses0.5 ( / (1 -  ) 2 ) Double hashing: Search hits (1 /  ) ln ( 1 / (1 -  ) ) Search misses1 / (1 -  )

56 56 / 57 DSA b) Očekávaný počet testů Linear probing: Plnění  1/22/33/49/10 Search hit Search miss Double hashing: Search hit Search miss Tabulka může být více zaplněná než začne klesat výkonnost. K dosažení stejného výkonu stačí menší tabulka.

57 57 / 57 DSA b) Expected number of probes Linear probing: Load factor  1/22/33/49/10 Search hit Search miss Double hashing: Search hit Search miss Table can be more full before performance degrades. - We need smaller table for the same performance.


Stáhnout ppt "Datové struktury a algoritmy Část 11 Rozptylování - Hashing Petr Felkel."

Podobné prezentace


Reklamy Google