Dynamiczne doskonałe mieszanie
W informatyce dynamiczne doskonałe mieszanie jest techniką programistyczną służącą do rozwiązywania kolizji w strukturze danych tablicy skrótów . Technika ta, choć zapytania , wstawić i usunąć duży zestaw elementów. wymaga więcej pamięci niż jej odpowiedniki z tablicą skrótów, jest przydatna w sytuacjach, w których należy wykonać szybkie
Detale
Sprawa statyczna
Schemat FKS
Problem optymalnego mieszania statycznego został po raz pierwszy ogólnie rozwiązany przez Fredmana, Komlósa i Szemerédiego. W swoim artykule z 1984 roku szczegółowo opisują dwupoziomowy schemat tablicy mieszającej, w którym każdy segment tablicy mieszającej (pierwszego poziomu) odpowiada oddzielnej tabeli mieszającej drugiego poziomu. Klucze są haszowane dwukrotnie — pierwsza wartość skrótu jest odwzorowywana na określony segment w tabeli skrótów pierwszego poziomu; druga wartość skrótu podaje pozycję tego wpisu w tabeli skrótów drugiego poziomu tego zasobnika. Gwarantuje się, że tabela drugiego poziomu będzie wolna od kolizji (tj. doskonałego haszowania ) po zbudowaniu. W konsekwencji gwarantowany jest koszt wyszukiwania na poziomie O(1) w najgorszym przypadku .
W przypadku statycznym otrzymujemy z wyprzedzeniem zestaw zawierający w sumie x wpisów, z których każdy ma unikalny klucz. Fredman, Komlós i Szemerédi wybierają tabelę skrótów pierwszego poziomu z wiaderkami o rozmiarze .
Aby skonstruować, x wpisów jest rozdzielanych na s segmentów przez funkcję haszującą najwyższego poziomu, gdzie . dla każdego zasobnika z k wpisami przydzielana jest tabela drugiego poziomu ze a jej funkcja skrótu jest wybierana losowo z uniwersalnego zestawu funkcji skrótu , tak aby była bezkolizyjna (tj. doskonała funkcja skrótu ) i przechowywana obok tablicy skrótów. Jeśli losowo wybrana funkcja mieszająca tworzy tabelę z kolizjami, nowa funkcja mieszająca jest wybierana losowo, dopóki nie będzie można zagwarantować bezkolizyjnej tabeli. Wreszcie, przy bezkolizyjnym mieszaniu, k wpisów jest mieszanych w tabeli drugiego poziomu.
Kwadratowy rozmiar przestrzeni zapewnia, że losowe tworzenie tabeli z kolizjami i niezależne od rozmiaru k zapewniając liniowy zamortyzowany czas budowy. Chociaż każda tabela drugiego poziomu wymaga przestrzeni skrótów pierwszego poziomu są rozmieszczone , struktura jako całość zajmuje oczekiwaną ponieważ rozmiary wiader są małe z dużym prawdopodobieństwem .
Funkcja skrótu pierwszego poziomu jest specjalnie dobrana tak, aby dla określonego zestawu x unikalnych wartości kluczy całkowita przestrzeń T używana przez wszystkie tabele skrótów drugiego poziomu oczekiwała miejsca , a dokładniej . Fredman, Komlós i Szemerédi wykazali, że biorąc pod uwagę uniwersalną rodzinę funkcji mieszających, co najmniej połowa z tych funkcji ma tę właściwość.
Przypadek dynamiczny
Dietzfelbinger i in. przedstawić algorytm dynamicznego słownika dodawany przyrostowo do słownika, zapytania o członkostwo zawsze działają w stałym czasie, a zatem w najgorszym przypadku całkowity wymagany O liniowy i oczekiwany zamortyzowany czas wstawiania i usuwania ( stały czas
W dynamicznym przypadku, gdy klucz jest wstawiany do tablicy skrótów, jeśli jego wpis w odpowiedniej podtabeli jest zajęty, wówczas mówi się, że zachodzi kolizja i podtabela jest odbudowywana na podstawie nowej całkowitej liczby wpisów i losowo wybranej funkcji skrótu. Ponieważ współczynnik obciążenia tabeli drugiego poziomu jest utrzymywany na niskim poziomie rzadka, a oczekiwany zamortyzowany koszt wstawiania wynosi . Podobnie, zamortyzowany oczekiwany koszt usunięcia wynosi .
Ponadto ostateczne rozmiary tabeli najwyższego poziomu lub którejkolwiek z podtabel są niepoznawalne w przypadku dynamicznym. Jedną z metod zachowania oczekiwanej w tabeli jest wywołanie pełnej rekonstrukcji, gdy nastąpi wystarczająca liczba Zgodnie z wynikami Dietzfelbingera i in., o ile całkowita liczba wstawień lub usunięć przekracza liczbę elementów w czasie ostatniej konstrukcji, zamortyzowany oczekiwany koszt wstawiania i usuwania pozostaje O ( 1 ) { z uwzględnieniem pełnego ponownego mieszania.
Implementacja dynamicznego doskonałego mieszania przez Dietzfelbingera i in. używa tych koncepcji, a także leniwego usuwania i jest pokazany w pseudokodzie poniżej.
Implementacja pseudokodu
Znajdź
funkcja Locate( x ) to j := h( x ) jeśli (pozycja h j ( x ) podtabeli T j zawiera x (nie usunięte)) return ( x jest w S ) koniec jeśli inaczej return ( x nie jest w S ) koniec inny koniec
Wstawić
Podczas wstawiania nowego wpisu x w punkcie j następuje zwiększenie globalnego licznika operacji count .
Jeśli x istnieje w j , ale jest oznaczone jako usunięte, to znak jest usuwany.
Jeśli x istnieje w j lub odbudowywana w podtabeli Tj i nie mieszającą hj jest oznaczone jako usunięte, to mówi się, że zachodzi kolizja, a tabela drugiego poziomu Tj zasobnika j jest z inną losowo wybraną funkcją .
funkcja Insert( x ) to liczba = liczba + 1; if ( count > M ) FullRehash( x ); koniec jeśli jeszcze j = h( x ); if (Pozycja h j (x) podtabeli T j zawiera x ) if ( x jest zaznaczone jako usunięte) usuń znacznik usuwania; koniec, jeśli koniec, jeśli inaczej b j = b j + 1; if ( b j <= m j ) jeśli pozycja h j ( x ) z T j jest pusta przechowuj x na pozycji h j ( x ) z T j ; end if else Umieść wszystkie niezaznaczone elementy T j na liście L j ; Dołącz x do listy L j ; b j = długość L j ; powtórz h j = losowo wybrana funkcja w H sj ; dopóki h j nie jest iniekcyjne na elementach L j ; dla wszystkich y na liście L j zapisz y na pozycji h j ( y ) z T j ; koniec dla końca else koniec, jeśli jeszcze m j = 2 * max{1, m j }; s jot = 2 * m jot * ( m jot - 1); jeśli suma wszystkich s j ≤ 32 * M 2 / s ( M ) + 4 * M Przydziel s j komórek dla T j ; Umieść wszystkie niezaznaczone elementy T j na liście L j ; Dołącz x do listy L j ; b j = długość L j ; powtórz h j = losowo wybrana funkcja w H sj ; dopóki h j nie jest iniekcyjne na elementach L j ; dla wszystkich y na liście L j zapisz y na pozycji h j ( y ) z T j ; koniec za koniec, jeśli jeszcze FullRehash( x ); koniec inny koniec inny koniec inny koniec inny koniec
Usuwać
Usunięcie x oznacza po prostu flagę x jako usuniętą bez usuwania i zwiększa liczbę przyrostów . W przypadku zarówno wstawiania, jak i usuwania, jeśli liczba osiągnie próg M , cała tablica jest odbudowywana, gdzie M jest pewną stałą wielokrotnością rozmiaru S na początku nowej fazy . Tutaj faza odnosi się do czasu między pełnymi przebudowami. Zauważ, że tutaj -1 w „Delete( x )” jest reprezentacją elementu, który nie znajduje się w zbiorze wszystkich możliwych elementów U .
funkcja Usuń( x ) to liczba = liczba + 1; j = godz( x ); jeżeli pozycja h j ( x ) podtabeli Tj zawiera x oznaczamy x jako usunięte; zakończ, jeśli w przeciwnym razie wróć (x nie jest członkiem S); koniec else if ( count >= M ) FullRehash(-1); koniec, jeśli koniec
Pełna przebudowa
Pełne przebudowanie tablicy S rozpoczyna się najpierw od usunięcia wszystkich elementów oznaczonych jako usunięte, a następnie ustawienia następnej wartości progowej M na pewną stałą wielokrotność rozmiaru S . Funkcja mieszająca, która dzieli S na podzbiory s ( M ), gdzie rozmiar podzbioru j wynosi s j , jest wybierana losowo, dopóki:
Wreszcie, dla każdej podtabeli Tj Tj funkcja , mieszająca hj hj jest wstrzyknięta wielokrotnie losowo wybierana spośród Hsj aż zostanie na elementy . Oczekiwany czas pełnej przebudowy tablicy S o rozmiarze n to O( n ).
funkcja FullRehash( x ) to Umieść wszystkie niezaznaczone elementy T na liście L ; jeśli ( x jest w U ) dołącz x do L ; koniec if liczba = długość listy L ; M = (1 + do ) * max { liczba , 4}; powtórz h = losowo wybrana funkcja w Hs (M) ; dla wszystkich j < s ( M ) utwórz listę L j dla h ( x ) = j ; b j = długość L j ; m jot = 2 * b jot ; s jot = 2 * m jot * ( m jot - 1); koniec aż suma wszystkich s j ≤ 32 * M 2 / s ( M ) + 4 * M dla wszystkich j < s ( M ) Przydziel miejsce s j dla podtabeli T j ; powtórz h j = losowo wybrana funkcja w H sj ; dopóki h j nie jest iniekcyjne na elementach listy L j ; koniec dla wszystkich x na liście L j przechowuj x na pozycji h j ( x ) z T j ; koniec za koniec