Betrachten Sie die einfach verknüpfte Liste in einer rein funktionalen Umgebung. Sein Lob wurde von den Berggipfeln gesungen und wird auch weiterhin gesungen. Hier werde ich auf eine seiner vielen Stärken und die Frage eingehen, wie sie auf die breitere Klasse rein funktionaler Sequenzen auf der Basis von Bäumen ausgedehnt werden kann.
Das Problem ist das Folgende: Sie möchten in O (1) -Zeit durch starkes Hashing auf nahezu sichere strukturelle Gleichheit testen. Wenn die Hash-Funktion strukturell rekursiv ist, dh hash (x: xs) = mix x (hash xs), können Sie Hash-Werte in Listen transparent zwischenspeichern und in O (1) -Zeit aktualisieren, wenn ein Element in eine vorhandene Liste aufgenommen wird . Die meisten Algorithmen für Hashing-Listen sind strukturell rekursiv, so dass dieser Ansatz in der Praxis hervorragend anwendbar ist.
Angenommen, Sie haben anstelle von einfach verknüpften Listen baumbasierte Sequenzen, die die Verkettung von zwei Sequenzen der Länge O (n) in der Zeit O (log n) unterstützen. Damit das Hash-Caching hier funktioniert, muss die Hash-Mischfunktion assoziativ sein, um die Freiheitsgrade zu berücksichtigen, die ein Baum bei der Darstellung derselben linearen Sequenz hat. Der Mischer sollte die Hash-Werte der Teilbäume nehmen und den Hash-Wert des gesamten Baums berechnen.
Hier war ich vor sechs Monaten, als ich einen Tag lang über dieses Problem nachdachte und es untersuchte. Es scheint in der Literatur zu Datenstrukturen keine Beachtung gefunden zu haben. Ich bin auf den Tillich-Zemor-Hashing-Algorithmus aus der Kryptographie gestoßen. Es basiert auf der 2x2-Matrixmultiplikation (die assoziativ ist), wobei die Bits 0 und 1 den beiden Generatoren einer Subalgebra mit Einträgen in einem Galois-Feld entsprechen.
Meine Frage ist, was habe ich vermisst? Es muss sowohl in der Literatur zu Kryptographie als auch zu Datenstrukturen relevante Artikel geben, die ich bei meiner Suche nicht gefunden habe. Alle Kommentare zu diesem Problem und möglichen Orten zu erkunden, wäre sehr dankbar.
Edit: Ich interessiere mich für diese Frage sowohl an den weichen als auch an den kryptografisch starken Enden des Spektrums. Auf der weicheren Seite kann es für Hash-Tabellen verwendet werden, bei denen Kollisionen vermieden werden sollten, aber nicht katastrophal sind. Auf der stärkeren Seite kann es für Gleichstellungstests verwendet werden.
Die fast universelle Familie von Hash-Funktionen
hat hier eine schöne Eigenschaft: , wobei "∘" die Verkettung bezeichnet. Wenn Sie an der Wurzel jedes Baums zwischenspeichern, werden sowohl sein Hash-Wert als auchein| → x | Sie können den Hash aus der Verkettung von zwei Bäumen in berechnenO(1)Operationen anZp.hein( x⃗ ) + a| x⃗ |hein( y⃗ ) = hein( x⃗ ∘y⃗ ) ∘ ein| x⃗ | O ( 1 ) Zp
Dies ist sowohl assoziativ als auch ziemlich schnell. Die Kollisionswahrscheinlichkeit von ist O ( min ( | → x | , | → y | ) / p ) . Siehe CLRS oder Dietzfelbinger et al. In "Polynomial Hash Functions Are Reliable".x⃗ ≠y⃗ O(min(|x⃗ |,|y⃗ |)/p)
quelle
Eine Lösung ist die Verwendung von Merkle-Hashing. Verwenden Sie eine unveränderliche / beständige binäre Baumdatenstruktur. Kommentieren Sie jeden Blattknoten mit dem Hash der Daten, die in diesem Blatt enthalten sind. Kommentieren Sie jeden internen Knoten mit dem Hash der Hashes für die beiden untergeordneten Knoten. Mit anderen Worten, wenn ein interner Knoten mit untergeordneten Knoten n ' , n " ist und diese mit den Hashwerten y ' , y " kommentiert wurden, sollten Sie den internen Knoten n mit dem Hashwert y = H ( y ' , Y' ' ) , wobei Hn n′,n′′ y′,y′′ n y=H(y′,y′′) H ist eine Hash-Funktion. Dies fügt allen Baumoperationen nur zusätzliche Arbeit pro erstelltem Knoten hinzu. Beispielsweise können Sie das Zusammenführen von zwei Bäumen in O ( lg n ) -Zeit unterstützen .O(1) O ( lgn )
quelle