Es gibt diese Datenstruktur, die die Leistung des Array-Zugriffs mit der Notwendigkeit vergleicht, sie beim Löschen zu durchlaufen. Sie führen mit jedem Eintrag einen Generationszähler sowie einen globalen Generationszähler. Die "Lösch" -Operation erhöht den Erzeugungszähler. Bei jedem Zugriff vergleichen Sie lokale und globale Generationszähler. Wenn sie sich unterscheiden, wird der Wert als "sauber" behandelt.
Dies ist in dieser Antwort auf Stack Overflow kürzlich aufgetaucht , aber ich erinnere mich nicht, ob dieser Trick einen offiziellen Namen hat. Macht es?
Ein Anwendungsfall ist der Dijkstra-Algorithmus, wenn nur eine winzige Teilmenge der Knoten gelockert werden muss und dies wiederholt erfolgen muss.
algorithms
terminology
krlmlr
quelle
quelle
Antworten:
Der vorgenannte Ansatz erfordert, dass jede Zelle eine Zahl halten kann, die groß genug ist, um die Anzahl der Neuinitialisierungen des Arrays zu halten, was eine erhebliche Raumstrafe darstellt. Wenn ein Slot in der Lage ist, mindestens einen Wert zu speichern, der niemals legitim geschrieben werden kann, kann vermieden werden, dass eine andere (nicht konstante) Platzstrafe auf Kosten der Hinzufügung einer
O(Wlg(N))
Zeitstrafe auftritt, wobeiW
die Anzahl der zwischengeschriebenen unterschiedlichen Array-Slots angegeben wird Löschvorgänge undN
ist die Größe des Arrays. Angenommen, man speichert Ganzzahlen von -2.147.483.647 bis 2.147.483.647 (aber niemals -2.147.483.648) und möchte, dass leere Array-Elemente als Null gelesen werden. Füllen Sie zunächst das Array mit -2.147.483.648 (nennen Sie diesen WertB
). Geben Sie beim Lesen eines Array-Steckplatzes für die Anwendung den WertB
Null an. Vor dem Array Schlitz SchreibenI
, zu prüfen , ob er gehalten ,B
und wenn ja , undI
größer als eins ist , eine Null speichern SchlitzI/4
nach einem ähnlichen Kontroll für diesen Ort durchführt (und, wenn es gehaltenB
,I/16
usw.).Beginnen Sie zum Löschen des Arrays mit
I
0 oder 1, je nach Array-Basis (der beschriebene Algorithmus funktioniert auch für beide). Wiederholen Sie dann den folgenden Vorgang: Wenn item gleichI
istB
, erhöhen SieI
und dividieren Sie durch vier, wenn dies ein Vielfaches von vier ergibt (beenden Sie, wenn die Division einen Wert von 1 ergibt); Ist diesI
nicht der FallB
, speichern SieB
es und multiplizieren Sie esI
mit vier (I
beginnt es bei Null, wird es mit vier multipliziert,I
wird es jedoch inkrementiert , da Punkt 0 leer sein wird).Man beachte, dass man die Konstante "vier" oben durch andere Zahlen ersetzen könnte, wobei größere Werte im Allgemeinen weniger Arbeitsmarkierungen erfordern, aber kleinere Werte im Allgemeinen weniger Arbeitslöschung erfordern; Da markierte Array-Slots gelöscht werden müssen, ist ein Wert von drei oder vier mit ziemlicher Sicherheit optimal. da der Wert vier sicherlich nahezu optimal ist, besser als zwei oder acht ist und bequemer als jede andere Zahl, scheint es die vernünftigste Wahl zu sein.
quelle
Ich würde es "Lazy Array Cell Reinitialization" nennen, aber es scheint keinen etablierten Namen zu haben (das heißt, der Name ist weit verbreitet).
Der Algorithmus ist clever, aber sehr spezialisiert und auf engstem Raum anwendbar.
quelle
Ich glaube, es ist ein Sonderfall des Auswendiglernen , außer dass in diesem Fall die "Memos" implizit mit jedem Inkrement des globalen Zählers "altern". Ich denke eine Art "Rückwärtserinnerung".
quelle