1 / 23

Algorytmy i struktury danych

Algorytmy i struktury danych. T ablice haszowane. Klucz. Klucz – „wyróżnik danych” np. data ur.+imię +nazwisko, pesel, nr dowodu, nr indeksu Założymy, że klucze to liczby, zawsze można zbudować funkcję transformującą np. napis na liczbę: Można np. zsumować kody odpowiadające literom

gertrude
Download Presentation

Algorytmy i struktury danych

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Algorytmy i struktury danych Tablice haszowane

  2. Klucz • Klucz – „wyróżnik danych” np. data ur.+imię +nazwisko, pesel, nr dowodu, nr indeksu • Założymy, że klucze to liczby, zawsze można zbudować funkcję transformującą np. napis na liczbę: • Można np. zsumować kody odpowiadające literom „ALA” -> 65+76+65

  3. Tablica z adresowaniem bezpośrednim Klucz Klucz Klucz Klucz Dane Dane Dane Dane T ! Małe uniwersum kluczy ! 0 1 2 3 4 3 2 5 6 K 5 7 8 8 9

  4. Adresowanie bezpośrednie - implementacja def DirectAdress_Search(table, key): return table[key] def DirectAdress_Insert(table, x): table[x.key] = x def DirectAdress_Delete(table, key): table[key] = None

  5. Tablica z funkcją haszującą Klucz Klucz Klucz Klucz Dane Dane Dane Dane Funkcja haszująca odwzorowuje klucz w przestrzeń adresową tablicy 0 1 2 3 Uniwersum wszystkich kluczy 4 k3 k2 5 6 K k5 7 k8 8 9

  6. Funkcja haszująca • F. haszująca - odwzorowuje klucz w przestrzeń adresową (zwykle mniejszą niż uniwersum), tj. dziedzinę poprawnych adresów tablicy • h(k) powinno należeć do przestrzeni adresowej tablicy dla dowolnego (legalnego) klucza Wymagania: • generowanie adresów dla rzeczywistego zbioru rekordów w sposób jak najbardziej równomierny (rozproszony) • łatwość obliczenia • Wskazane jest sprawdzenie wybranej f. haszująca na fragmencie rzeczywistych danych

  7. Haszowanie modularne h(k) = k mod m, gdzie m jest rozmiarem tablicy • Dobre m nie powinno być równe 2p, 10p – gdyż takie haszowanie ignoruje bardzo znaczące bity (cyfry) • Dobre m nie powinno być równe 2p-1, 10p-1 gdyż daje identyczne wartości na ciągach, dla których przestawiono bity (cyfry) • Niezłe są np. liczby pierwsze niezbyt bliskie potęgom 2

  8. Haszowanie przez mnożenie h(k) = m (kA mod 1), gdzie kA mod 1 = kA A zwykle jest liczbą z przedziału 0..1 m jest zwykle potęgą 2 lub 10, gdyż wtedy h(k) = pewna ilość cyfr po przecinku z kA • W praktyce bardzo dobre A to np. (sqrt(5)-1)/2 = 0.6180339887....

  9. Haszowanie przez randomizację h(k) = Rand (k) • Metoda kwadratu środka: wydziel z klucza pewną jego część (np. środek), potraktuj jako liczbę binarną, po czym podnieś ją do kwadratu. • Metoda składania: podziel klucz na części (segmenty), potraktuj je jako liczby binarne, po czym dodaj je do siebie arytmetycznie. • Metoda sumy modulo 2: podziel klucz na części (segmenty), potraktuj je jako ciągi bitów i dodaj je do siebie modulo 2. • W praktyce dla uzyskania dobrej losowości wymagane sa duże wartości stad często stosuje się ta metode w połączeniu z h. modularnym

  10. Haszowanie uniwersalne H – rodzina funkcji haszujących Na początku pracy losowo wybieramy jedną funkcję haszującą z całej rodziny i stosujemy ją od tej poryhH • Brak możliwości „złośliwego” doboru elementów

  11. Rozwiązywanie kolizji przez łańcuchowanie oddzielne • Listy zawierają elementy, dla których h(k) jest takie samo-synon. • Kolejność elementów na liście jest przypadkowa 0 1 2 k12 Dane k2 Dane 3 k3 Dane 4 k5 k3 k15 5 Dane Dane k12 k2 6 k15 k5 7 k8 8 k8 Dane 9 h(k) = k mod 10

  12. Łańcuchowanie oddzielne – impl. def ChainHash_Search(table, key): return FindInList(table[h(key)], key) def ChainHash_Insert(table, x): pos = h(x.key)table[pos] = AddHead(table[pos],x) def ChainHash_Delete(table, key): pos = h(x.key)table[pos] = DeleteFromList(table[pos],key)

  13. Łańcuchowanie oddzielne - właściwości  - współczynnik zapełnienia  = ilość elementów / rozmiar tablicy • Pesymistyczny czas wyszukiwania = (n) Jeżeli h rozmieszcza klucze równomiernie, to • dla Oczekiwany czas wyszukiwania = (1+ )

  14. Adresowanie otwarte • Dla rozwiązywania konfliktów nie stosuje się list • Wszystkie elementy (wskaźniki) zapisywane są bezpośrednio w tablicy h(k, i) = (h’(k) + g(i)) gdzie: k – klucz, i – numer próby (0..N-1), N – rozmiar tablicy Aby umieścić element w tablicy sprawdzamy h(k, 0) jeśli zajęte, to h(k, 1) itd aż do h(k, N-1).

  15. Adresowanie otwarte przykład kolizji 1 • Kolejność dodawania: k12, k2, k4, k3 k12 Dane 2 k2 Dane 3 Dane k4 4 k3 k12 k2 5 k3 Dane 6 k4 7 8 h(k) = (k+i) mod 10 9

  16. Adresowanie otwarte – implem. def Hash_Insert(table, x): for i in range(i, MAX): j = h(x.key, i) if table[j] == None: table[j] = x return ERROR „przepełnienie tablicy”

  17. Adresowanie otwarte – implem. def Hash_Search(table, key): for in range(0, MAX): j = h(key, i) if table[j] == None: return None if table[j].key == key: return table[j] return None

  18. Adresowanie otwarte – usuwanie elementów Problem: Nie można wpisywać None Rozwiązanie: • Nowa stała np.: DELETED • Należy wtedy zmodyfikować przeszukiwanie ......... if table[j] == None: return None if table[j] == DELETED: continue if table[j].key == key: return table[j] • i dodawanie if table[j] == Noneortable[j] == DELETED:

  19. Rodzaje adresowania otwartego • Liniowe: h(k,i) = (h’(k) + i ) mod m • Wadą jest grupowanie się elementów • Kwadratowe: h(k,i) = (h’(k) + c1i + c2i2) mod m • Wadą jest (mniej groźne) grupowanie wtórne • Sześcienne: h(k,i) = (h’(k) + c1i + c2i2 + c3i3) mod m • Wadą jest (mniej groźne) grupowanie wtórne • Dwukrotne: h(k,i) = (h1(k) + h2(i)) mod m • Grupowanie wtórne jest znikome

  20. Metoda otwarta - właściwości  - współczynnik zapełnienia  = ilość elementów / rozmiar tablicy • Pesymistyczny czas wyszukiwania = (n) Dla liniowej funkcji g oczekiwany czas wyszukiwania z sukcesem 1+1/(1- )z porażką to 1+1/(1- )2 Dla pseudolosowej funkcji g oczekiwany czas wyszuk. z sukcesem -1 (1+ln (1/(1- ))) z porażką to 1/(1- )

  21. Uniwersum kluczy • Powinno byćnie mniejsze niż rozmiar tablicy • Sumowanie kodów liter np. „ALA” -> 65+76+65Stosunkowo mały rozmiar uniwersum, np. dla 30 znaków 30*256 = 7680 • Sumowanie par (lub dłuższych ciągów liter), co daje większą przestrzeń adresów „ALA” -> 65*256+76 + 65*256W uniwersum są „dziury” bo np. znaki mają kody >=32 i zwykle mniejsze niż 127 • Suma iloczynów kodów par „ALA” -> 65*76 + 65Nierównomierny rozkład wartości, np. więcej l. parzystych

  22. Przykład Tablica 106 elementów adresowana nazwiskiem i imieniem • Znaki: • W ogólności jeden znak dla ASCII 0-255. • 0-32 - znaki niedrukowalne, 32-47, 91-96, 123-127 znaczki różne, 48-57 cyfry, 65-90, 97-122 – litery, 128-255 znaki graficzne (polskie litery) • UNICODE – jeden znak 0 – (216-1), dużo bardzo rzadko używanych znaków. • Przy obliczeniach można pominąć znaki różne od liter (ewentualnie cyfr) • Polskie znaki diakrytyczne: można zamienić na ich łacińskie odpowiedniki lub pominąć. • Zamieniamy znaki na małe. Stąd jeden znak może mieć kod od 97 do 122. • log122-97+1106 = log26106 = 4.24. Czyli maksymalna waga dla znaku powinna wynosić co najmniej 265.

  23. Przykład MAXP = 5 BASE = ord("Z")-ord("A")+1 def K(key): for c in key: c = Convert(c)# konwersja na duze litery + # ew zamiana polskich znakówif c>="A" and c<="Z": digit = ord(c)–ord("A")keyVal = keyVal + digit * pow(BASE, p) p = (p+1) % (MAXP+1) return keyVal

More Related