Update: Im Folgenden finden Sie ein Update zur Fehlerhaftigkeit dieses Join-Vorgangs
Hier ist eine sehr grobe Skizze einer möglichen Lösung:
Ich glaube, ich habe eine Lösung für dieses Problem mit einer Art zufällig ausgewogenem B + -Baum. Diese Bäume haben wie Treaps eine einzigartige Repräsentation. Im Gegensatz zu Treaps speichern sie einige Schlüssel mehrmals. Es könnte möglich sein, dies mit einem Trick aus Bent et al. "Biased Search Trees" zu beheben, bei dem jeder Schlüssel nur in der höchsten (dh der Wurzel nächstgelegenen) Ebene gespeichert wird, in der er erscheint.
Ein Baum für einen geordneten Satz eindeutiger Werte wird erstellt, indem zunächst jedem Wert ein Bitstrom zugeordnet wird, ähnlich wie jedem Wert in einem Treap eine Priorität zugeordnet wird. Jeder Knoten im Baum enthält sowohl einen Schlüssel als auch einen Bitstrom. Nicht-Blattknoten enthalten zusätzlich eine natürliche Zahl, die die Höhe des Baums angibt, der an diesem Knoten verwurzelt ist. Interne Knoten können eine beliebige Anzahl von Kindern ungleich Null haben. Wie bei B + -Bäumen ist jeder sich nicht selbst schneidende Pfad von der Wurzel zu einem Blatt gleich lang.
Jeder interne Knoten enthält (wie in B + -Bäumen) den größten Schlüssel k seiner Nachkommenblätter. Jedes enthält auch eine natürliche Zahl i , die die Höhe des Baums angibt, der bei v verwurzelt ist , und den Strom von Bits, die mit k ab dem i + 1- ten Bit verknüpft sind. Wenn jeder Schlüssel in dem Baum, der mit v verwurzelt ist, dasselbe erste Bit in seinem Bitstrom hat, ist jedes Kind von v ein Blatt und i ist 1 . Andernfalls sind die Kinder von v interne Knoten, von denen alle das gleiche i- te Bit in dem ihrem Schlüssel zugeordneten Bitstrom haben.vkichvki + 1vvich1vich
Um einen Baum aus einer sortierten Liste von Schlüsseln mit zugeordneten Bitströmen zu erstellen, sammeln Sie zuerst die Schlüssel in zusammenhängenden Gruppen basierend auf dem ersten Bit in ihren Streams. Erstellen Sie für jede dieser Gruppen ein übergeordnetes Element mit dem Schlüssel und dem Bitstrom des größten Schlüssels in der Gruppe, aber ohne das erste Bit des Stroms. Führen Sie nun das gleiche Gruppierungsverfahren für die neuen Eltern durch, um Großeltern zu erstellen. Fahren Sie fort, bis nur noch ein Knoten übrig ist. Das ist die Wurzel des Baumes.
Die folgende Liste der Schlüssel und (Anfangs-) Bitströme wird durch den Baum darunter dargestellt. In den Bitstrom-Präfixen ist ein '.' bedeutet ein bisschen. Das heißt, jeder Bitstrom für den Schlüssel A mit einer 0 erzeugt an erster Stelle den gleichen Baum wie jeder andere, vorausgesetzt, kein Bitstrom eines anderen Schlüssels ist unterschiedlich.
A 0...
B 00..
C 10..
D 0...
E 0011
F 1...
G 110.
H 0001
____H____
/ \
E H
| / \
__E__ G H
/ | \ | |
B C E G H
/ \ | / \ / \ |
A B C D E F G H
Jedes Kind eines bestimmten internen Knotens hat an erster Stelle seines Bitstroms das gleiche Bit. Dies nennt man die "Farbe" des Elternteils - 0 ist rot, 1 ist grün. Das Kind hat einen "Geschmack", der vom ersten Bit seines Bitstroms abhängt - 0 ist Kirsche, 1 ist Minze. Blätter haben Aromen, aber keine Farbe. Per Definition kann ein Kirschknoten keinen grünen Elternknoten und ein Minzknoten keinen roten Elternknoten haben.
n21 - n ( n - 1i - 1)( n + 1 ) / 2n ≥ 2≤ 34nO ( lgn )
Um zwei Bäume gleicher Höhe zu verbinden, prüfen Sie zunächst, ob ihre Wurzeln die gleiche Farbe haben. Wenn ja, trennen Sie von der linken Wurzel das am weitesten rechts stehende Kind und von der rechten Wurzel das am weitesten links stehende Kind, und verbinden Sie diese beiden Bäume rekursiv. Das Ergebnis ist ein Baum mit der gleichen Höhe oder einer Höhe, da die Bäume den gleichen Geschmack haben (siehe unten). Wenn das Ergebnis des rekursiven Verbindens der beiden Bäume dieselbe Höhe hat wie die beiden abgetrennten Kinder, machen Sie es zum mittleren Kind einer Wurzel, wobei die verbleibenden Kinder der linken Wurzel davor und die verbleibenden Kinder der rechten Wurzel danach liegen. Wenn es um 1 größer ist, machen Sie seine Kinder zu den mittleren Kindern einer Wurzel mit den verbleibenden Kindern der linken Wurzel davor und den verbleibenden Kindern der rechten Wurzel danach. Wenn die Wurzeln unterschiedliche Farben haben, prüfen Sie, ob sie den gleichen Geschmack haben. Wenn sie es tun, Geben Sie ihnen ein neues übergeordnetes Element mit dem Schlüssel und dem Bitstrom der rechten Wurzel, wobei das erste Bit entfernt wird. Wenn dies nicht der Fall ist, geben Sie jeder Wurzel ein neues übergeordnetes Element mit dem Schlüssel und dem Bitstrom der alten Wurzel (wobei jedes erste Bit entfernt wird) und verbinden Sie diese Bäume dann rekursiv.
1 / 21 / 2O ( 1 )1 / 4und nachfolgende rekursive Aufrufe beziehen sich immer auf Bäume mit unterschiedlichen Farben, sodass die gleiche Analyse angewendet wird.
1 / 2O ( 1 )
O ( 1 )
a 01110
b 110..
c 10...
d 00000
Der von gemachte Baum [a,b]
hat eine Höhe von 2, der von gemachte Baum [c,d]
hat eine Höhe von 2 und der von gemachte Baum joinEqual (tree [a,b]) (tree [c,d])
hat eine Höhe von 3. Der von gemachte Baum [a,b,c,d]
hat jedoch eine Höhe von 5.
Hier ist der Code, mit dem ich diesen Fehler gefunden habe .