Algorytmy i struktury danych Wykład 4 Tablice nieporządkowane i uporządkowane
Tablice uporządkowane Szukanie binarne Szukanie interpolacyjne
Tablice uporządkowane Szukanie binarne O(log N) Szukanie interpolacyjne O(log log N)
Tablice uporządkowane Jak wstawić element do tablicy uporządkowanej?
Tablice uporządkowane Jak wstawić element do tablicy uporządkowanej? 1. Znaleźć miejsce tego elementu (szukanie binarne) Przesunąć pozostałe elementy o jeden w prawo
Tablice uporządkowane Jak wstawić element do tablicy uporządkowanej? Koszt tej operacji: Szukanie: logarytmiczny Przesuwanie elementów: (średnio N/2) liniowy
Tablice uporządkowane Jak wstawić element do tablicy uporządkowanej? Koszt tej operacji: Szukanie: logarytmiczny Przesuwanie elementów: (średnio N/2) liniowy Razem otrzymujemy (N)
Tablice uporządkowane Jak wstawić element do tablicy uporządkowanej? 2. Wstawienie elementu na koniec, zamiana miejsc z kolejnymi elementami do momentu znalezienia właściwego miejsca.
Tablice uporządkowane Jak wstawić element do tablicy uporządkowanej? Koszt tej operacji: Liniowy (średnio N/2 elementów) Razem otrzymujemy (N)
Tablice uporządkowane Uwagi Przestawianie może wymagać więcej czasu. Wstawianie elementu do tablicy nieuporządkowanej: (1) (jeżeli znamy adres)
Tablice uporządkowane Jak wykonać operację usuwania elementu?
Tablice uporządkowane Jak wykonać operację usuwania elementu? Należy znaleźć jego miejsce, usunąć, przesunąć Kolejne elementy tablicy (analogicznie jak przy wstawianiu). Razem (N)
Tablice uporządkowane Przeglądanie tablicy uporządkowanej: (N) Tablica nieuporządkowana wymaga posortowania.
Algorytmy i struktury danych Wykład 4 cz. 1
Motywacja Wiele problemów wymaga dynamicznych zbiorów danych, na których można wykonywać operacje: wstawiania (Insert) szukania (Search) Usuwania (Delete)
Motywacja Taki abstrakcyjny typ danych nazywamy słownikiem.
Motywacja Słowniki są potrzebne np. w: -Bazach danych -Kompilatorach (tłumaczenie składni programu, kluczami są komendy bazowe danego języka) -Zastosowaniach sieciowych
Efektywnym sposobem implementacji takich typów danych są tablice z techniką dostępu nazywaną rozproszoną (hash tables).
Polega one na obliczaniu adresu danego elementu (rekordu) na podstawie fragmentu tego rekordu zwanego kluczem. Umożliwia to (zazwyczaj) odnalezienie danego rekordu w jednej próbie.
Formalnie możemy rozważyć problem: Dany jest zbiór rekordów S z których każdy identyfikowany jest przez unikatowy kluczem k ze zbioru K, oraz zbiór adresów pamięci A.
Znaleźć odwzorowanie H K->A, takie, że nakład pracy z odnalezienia rekordu o danym kluczu jest minimalny.
Odwzorowanie H jest zazwyczaj odwzorowaniem wiele do jednego gdyż liczba rekordów S jest większa niż liczebność zbioru A.
Czasami rzeczywistych rekordów będzie mniej niż wynosi liczba możliwych rekordów. Przykład: Baza danych nazwisk ok. 26^10 wszystkich możliwych rekordów.
Załóżmy, że zbiorem adresów pamięci A jest zbiór indeksów tablicy T: {0,,M-1}. Algorytm poszukiwania rekordu o kluczu k jest Następujący: 1. Oblicz h = H(k) 2. Sprawdź zawartość T[h]
1. Oblicz h = H(k) 2. Sprawdź zawartość T[h] Jeżeli T[h] jest puste to koniec (nie ma rekordu) Jeżeli T[h].klucz ==k to wynik == k i koniec (jest rekord) Jeżeli T[h].klucz!=k to co?
Algorytm pozostawia niejasności: 1. Jak wybrać funkcję H? 2. Co zrobić gdy różne rekordy (ich klucze) dają tą samą wartość funkcji rozpraszającej (gdy występują kolizje)?
Trochę terminologii 1. Wartość H(k) nazywamy pseudokluczem 2. Kolizją nazywamy sytuację gdy H(k) daje taki sam pseudoklucz dla różnych k 3. Rekordy o tej samej wartości pseudoklucza nazywamy synonimami.
1. Jak wybrać funkcję H? Adresowanie bezpośrednie H(k) = k Prosta technika działająca dobrze dla małej liczebności zbioru S.
1. Jak wybrać funkcję H? Uwagi ogólne: Założenie prostego jednorodnego rozpraszania: każdy klucz ma jednakowe prawdopodobieństwo rozpraszania na każdy slot pamięci, niezależnie od wartości funkcji rozpraszającej dla innych kluczy.
1. Jak wybrać funkcję H? Uwagi ogólne: Większość funkcji rozpraszających jako argumenty Przyjmuje wartości liczb naturalnych N={0,1,2, }. Potrzebny sposób na przekształcanie kluczy w innym formacie na liczby naturalne.
1. Jak wybrać funkcję H? Randomizacja: H(k) = Rand(k) <- generator licz losowych na podstawie k Dla danego k musi zawsze zwracać tę samą Wartość. Można skorzystać z gotowej implementacji.
1. Jak wybrać funkcję H? Inne metody randomizacji: Kwadrat środka (wybieramy część np. środek danej liczby i podnosimy do kwadratu) Metoda składania (podział klucza na segmenty, operacja na segmentach np. suma liczb)
Metoda randomizacji Problem: Dla rzeczywistych danych trudno znaleźć sposób randomizacji o dużym stopniu losowości Trzeba zaimplementować sposób randomizacji tak by nie wyjść poza zakres tablicy (ograniczenie możliwości randomizacji)
Metoda dzielenia H(k) =k mod m <-reszta z dzielenia przez m Np. k=100, m=12 H(100) = 4 Pojedyncza operacja dzielenia działa dość szybko
Metoda dzielenia Uwagi: Należy wykluczyć pewne liczby m. Np. dla m=2^p H(k) to p ostatnich bitów k. Dla pewnych danych może prowadzić do niejednorodności. Przykład: nazwiska Kowalski, Nowakowski,
Metoda mnożenia H ( k) m (ka mod 1) 0 A 1 (ka mod1) ka ka Tym razem wartość m nie ma dominującego Wpływu, można przyjąć np. 2^p.
Jak wybrać p? Dobrym wyborem są np. liczby pierwsze niezbyt blisko potęg 2.
Jak wybrać p? Dodatkowo metodę można zoptymalizować po wartościach stałej A np. A 5 1 0,618033 2
Metody rozwiązywania kolizji 1. Łańcuchowanie oddzielne 2. Łańcuchowanie bezpośrednie 3. Adresowanie otwarte
1. Łańcuchowanie oddzielne Z tablicą rekordów Z tablicą odsyłaczy Tworzymy listę (jedno lub dwukierunkową) dla elementów które są adresowane do tego samego miejsca w pamięci
1. Łańcuchowanie oddzielne Wyszukanie rekordu sprowadza się do przeszukania listy odpowiadającej danej wartości funkcji rozpraszającej.
Algorytm wstawiania rekordu: 1. Oblicz wartość pseudoklucza 2. Sprawdź czy w tablicy ten adres jest wolny Jeśli tak, wpisz rekord i zakończ Jeśli nie przejdź dalej 3. Sekwencyjnie przeszukuj listę synonimów, sprawdzając czy rekord nie jest już wpisany. 4. Jeżeli jest zakończ, jeżeli nie jest, dopisz rekord.
1. Łańcuchowanie oddzielne Do analizy przydatny będzie parametr n m Gdzie n to liczba rekordów a m to liczba komórek Pamięci w tablicy
Algorytm wstawiania rekordu: 1. Oblicz wartość pseudoklucza 2. Sprawdź czy w tablicy ten adres jest wolny Jeśli tak, wpisz rekord i zakończ Jeśli nie przejdź dalej 3. Sekwencyjnie przeszukuj listę synonimów, sprawdzając czy rekord nie jest już wpisany. 4. Jeżeli jest zakończ, jeżeli nie jest, dopisz rekord.
Łańcuchowanie oddzielne: analiza Założenia: 1. obliczenie funkcji rozpraszającej (1) 2. Jednorodne rozpraszanie (każdy klucz ma jednakowe prawdopodobieństwo dać dany pseudoklucz)
Łańcuchowanie oddzielne: analiza Poszukiwanie zakończone porażką (wartość oczekiwana) (1+ ) Dlaczego?
Łańcuchowanie oddzielne: analiza Poszukiwanie zakończone sukcesem (wartość oczekiwana) (1+ )
Łańcuchowanie bezpośrednie Lista synonimów przechowywana jest w obszarze głównym a nie nadmiarowym.
Średnia liczba sondowań: S S S P 1 2 1 e 2 1 8 4 1 2 1 e 2 1 4