Istnieje taka struktura danych, która handluje wydajnością dostępu do tablicy w porównaniu z potrzebą iteracji po jej wyczyszczeniu. Utrzymujesz licznik generacji przy każdym wpisie, a także licznik generacji globalnej. Operacja „wyczyść” zwiększa licznik generacji. Przy każdym dostępie porównujesz liczniki generacji lokalnej i globalnej; jeśli się różnią, wartość jest traktowana jako „czysta”.
To pojawiło się ostatnio w odpowiedzi na Stack Overflow , ale nie pamiętam, czy ta sztuczka ma oficjalną nazwę. Czy to?
Jednym z przypadków użycia jest algorytm Dijkstry, jeśli tylko niewielki podzbiór węzłów musi być rozluźniony, i jeśli trzeba to powtarzać wielokrotnie.
algorithms
terminology
krlmlr
źródło
źródło
Odpowiedzi:
Wspomniane wyżej podejście wymaga, aby każda komórka mogła pomieścić liczbę wystarczająco dużą, aby pomieścić liczbę ponownych inicjalizacji macierzy, co stanowi znaczną karę przestrzenną. Jeśli miejsce jest w stanie pomieścić co najmniej jedną wartość, która nigdy nie zostanie zapisana w sposób zgodny z prawem, można uniknąć kary pieniężnej za inne kary (nietrwałe) kosztem dodania
O(Wlg(N))
kary czasowej, gdzieW
jest liczba różnych miejsc tablic zapisanych między operacje czyszczenia iN
jest to rozmiar tablicy. Załóżmy na przykład, że będziemy przechowywać liczby całkowite od -2 147 483 647 do 2 147 483 647 (ale nigdy -2 147 483 648) i chcemy, aby puste elementy tablicy były odczytywane jako zero. Zacznij od wypełnienia tablicy -2 147 483 648 (wywołaj tę wartośćB
). Czytając miejsce na tablicę dla aplikacji, zgłoś wartość równąB
zero. Przed napisaniem gniazdo tablicowąI
, należy sprawdzić, czy jest utrzymywaneB
, a jeśli tak, iI
jest większa niż jeden, należy przechowywać zero do gniazdaI/4
po wykonaniu podobny czek na tym miejscu (i, jeśli to odbyłoB
,I/16
itp).Aby wyczyścić tablicę, zacznij od wartości
I
równej 0 lub 1, w zależności od podstawy tablicy (opisany algorytm będzie działał dla obu). Następnie powtórz następującą procedurę: Jeśli pozycjaI
jestB
, przyrostI
i, jeśli to daje wielokrotność czterech, podziel przez cztery (zakończ, jeśli dzielenie daje wartość 1); jeśli elementI
nie jestB
, zapisz goB
i pomnóżI
przez cztery (jeśliI
zaczyna się od zera, pomnożenie przez cztery pozostawi go zero, ale ponieważ element 0 będzie pusty,I
zostanie zwiększony).Zauważ, że można zastąpić stałą „cztery” powyżej innymi liczbami, przy czym większe wartości zwykle wymagają mniejszego oznaczania pracy, ale mniejsze wartości zwykle wymagają mniejszego czyszczenia pracy; ponieważ gniazda tablicowe, które są oznaczone, muszą zostać wyczyszczone, wartość trzech lub czterech jest prawie na pewno optymalna; ponieważ wartość cztery jest z pewnością zbliżona do optymalnej, jest lepsza niż dwie lub osiem i jest wygodniejsza niż jakakolwiek inna liczba, wydaje się to najbardziej rozsądnym wyborem.
źródło
Nazwałbym to „ponownym zainicjowaniem komórki leniwej macierzy”, ale wydaje się, że nie ma ona żadnej ustalonej nazwy (to znaczy, nazwa jest w powszechnym użyciu).
Algorytm jest sprytny, ale bardzo wyspecjalizowany i ma zastosowanie w bardzo wąskim obszarze.
źródło
Uważam, że jest to szczególny przypadek zapamiętywania , z wyjątkiem tego przypadku, że „notatki” domyślnie „starzeją się” z każdym przyrostem licznika globalnego. Chyba coś w rodzaju „zapamiętywania wstecznego”.
źródło