Intervall Heaps Studienarbeit von Thomas Schwanck am Institut für Informationssysteme Fachgebiet Programmiersprachen und Übersetzer Prof. Dr. R. Parchmann 2004 auf Basis des Artikels Interval Heaps von J. van Leeuwen and D. Wood The Computer Journal Vol. 36 Nr. 3 1993 S.209-216 Intervall Heaps 1. Einführung Sei X eine total geordnete Menge von Werten. (z.B. eine Untermenge von R). Eine double-ended oder min-max Priority Queue ist eine Datenstruktur für endliche Untermengen Y von X die die folgenden Operationen erlaubt: 1. MIN - bestimme den kleinsten Wert. 2. MAX - bestimme den größten Wert. 3. INSERT(x) - füge den Wert x ∈ X der Menge Y hinzu. 4. DELETEMIN - entferne das kleinste Element. 5. DELETEMAX - entferne das größte Element. wobei vorausgesetzt sei, daß der Leser die entsprechenden Operationen für normale Heaps kennt. Es können noch weitere Operationen eingeführt werden, wie z.B. das Ersetzen von Elementen (entspricht einer Prioritätsveränderung, wenn der Wert eines Eintrags seine Priorität ist) oder das Verschmelzen von Priority Queues, die hier aber nicht weiter betrachtet werden sollen. Es wird eine effiziente implizite Datenstruktur für double-endede Priority Queues, also eine Datenstruktur zur Verwaltung einer Menge von n Punkten aus X in den Positionen A [0] bis A [n − 1] eines Arrays A ohne zusätzliche Zeiger, die die oben aufgeführten Operationen mit einem Zeitbedarf von O(log n) oder schneller unterstützt vorgestellt, die Heaps in einer konsequenten Weise verallgemeinert. Diese Datenstruktur nennt sich Intervall Heap und besteht im wesentlichen aus einem Heap, in dem fast alle Knoten ein Paar von Punkten a, b (mit a ≤ b) aus der zu verwaltenden Menge Y tragen. Die beiden Punkte eines Paares werden als Endpunkte eines Intervalls aus X betrachtet. Die normale Heapeigenschaft wird durch die Inklusion ersetzt, d.h. das Intervall eines Knoten enthält die Intervalle aller seiner Nachfolger. Ist [a, b] das Intervall in der Wurzel, dann impliziert diese Heapeigenschaft, das a das aktuelle Minimum der Punkte in Y und b das aktuelle Maximum von Y ist. Eine präzisere Definition von Intervall Heaps wird in Abschnitt 2 gegeben. Dort wird zudem gezeigt, das sich Intervall Heaps mit einem Zeitbedarf von O(n) erzeugen lassen, die MIN- und MAX-Operationen einen Zeitbedarf von O(1) haben und für die anderen Operationen höchstens O(log n) Zeiteinheiten benötigen. In Abschnitt 3 soll die d -dimensionale Verallgemeinerung von Intervall Heaps betrachtet werden, in Abschnitt 4 werden ein paar Beispiele zur Anwendung von Intervall Heaps behandelt und im Abschnitt 5 Meßwerte und Details der Implementation. 1 Intervall Heaps 2. Intervall Heaps Es wird die Binärbaum Darstellung von Heaps benutzt, um die Diskussion der Intervall Heaps zu vereinfachen. Dabei sollte beachtet werden, das sich alle Manipulationen durch einfache Adressrechnungen auf die Darstellung mit einem Array H übertragen lassen. Zudem sollte beachtet werden, das hier das Konzept der Heaps von den Details der Darstellung der Punkte und der Ordnungrelation zwischen ihnen getrennt wird. Dadurch können beliebige Objekte in den Knoten enthalten sein, solange es eine Ordnungsrelation zwischen ihnen gibt und die Objekte mit der Idee der Heaps harmonisieren. Ein Intervall Heap ist ein fast vollständiger Baum (d.h. alle Ebenen bis auf die unterste sind vollständig gefüllt, nur in der untersten Ebene dürfen rechts beliebig viele Plätze frei sein.), in dem jeder Knoten ein Intervall [a, b] ∈ X repräsentiert. Sei I(v) das von dem Knoten v repräsentierte Intervall. Der nte (und letzte) Knoten des Heaps trägt die Bezeichnung left-hand node oder, kürzer, die L-node des Heaps. Definition 2.1 Ein Intervall Heap ist eine Heapstruktur die entweder leer ist oder die folgenden drei Bedingungen erfüllt (die Intervall Heapeigenschaft): 1. Für jeden Knoten v, der nicht die L-node ist, ist I(v) ein Intervall [a, b] mit a, b ∈ X. 2. Für die L-node ist I(v) entweder ein einzelner Wert a, wobei a ∈ X, oder ein Intervall [a, b] mit a, b ∈ X. 3. Für alle Knoten v und w gilt, falls v ein Nachfolger von w ist, I(v) ⊆ I(w). In der Definition wird zwischen einem einzelnen Punkt a und dem Intervall [a, a] unterschieden, da eigendlich zwei Werte aus X nötig sind, um ein Intervall zu definieren. Um die Diskussion zu vereinfachen, wird die ⊆-Relation so erweitert, das die Inklusion einer einzelnen Zahl in einem Intervall ebenfalls abgedeckt wird. Ein Intervall Heap enthält die Menge von Punkten die aus den Elementen von X besteht, die die linken und rechten Endpunkte der Intervalle des Intervall Heaps bilden und, falls die L-node kein Intervall enthält, das Element aus der L-node. Das Hauptergebnis dieses Abschnitts ist, das Intervall Heaps eine effiziente implizite Datenstruktur zur Implementation von double-ended Priority Queues sind. 2 Intervall Heaps Beachtet man, das ein Intervall Heap mit n Knoten eine Menge mit 2n − 1 oder 2n Elementen repräsentiert, dann ist es sofort klar, das man durch sukzessives Einfügen von Elementen in einen leeren Intervall Heap jede endliche Menge mit einem Intervall Heap darstellen kann. Das Einfügen in einen Intervall Heap ist im wesentlichen derselbe Algorithmus wie bei einem normalen Heap, hier auf den Heaps, die aus den linken bzw. rechten Intervallenden (zusammen mit dem Wert der L-node, falls diese kein Intervall ist) bestehen. Der Heap, der aus allen linken Intervallenden besteht, ist ein Min-Heap, der aus den rechten Intervallenden ein Max-Heap. Diese Heaps werden die zugrundeliegenden Min- und Max-Heaps genannt. Lemma 2.2 Intervall Heaps unterstützen die INSERT Operation in mit einem Zeitbedarf von O(log n). Beweis: Um ein Element N den Intervall Heap hinzuzufügen, wird anhand der L-node entschieden, in welchen der zugrundeliegenden Heaps das neue Element eingefügt wird. Als erstes erhält man die folgenden Fälle: 1. Die L-node enthält ein Intervall. Es seien L und R das linke bzw. das rechte Intervallende. Dann erhält man die 3 folgenden Fälle: • N < L: Füge N in den zugrundeliegen Min-Heap ein und erzeuge eine neue L-node mit einem Element. • L ≤ N ≤ R: erzeuge mit N eine neue L-node. • R < N : Füge N in den zugrundeliegendes Max-Heap ein und erzeuge eine neue L-node. 2. Die L-node enthält einen einzelnen Wert. Dann erhält man 2 Fälle, die analog zum obigen Fall behandelt werden können, nur das hier keine neue L-node erzeugt werden muß. Die Fallunterscheidung hat einen Zeitbedarf von O(1), das Einfügen des neuen Elementes in einen der zugrundeliegenden Heaps benötigt einen Zeitbedarf von O(log n), also insgesamt hat das Einfügen eines neuen Elementes in einen Intervall Heap einen Zeitbedarf von O(log n). ❏ 3 Intervall Heaps Lemma 2.3 Intervall Heaps benötigen für die DELETEMIN und die DELETEMAX Operation einen Zeitbedarf von O(log n). Beweis: Es wird hier nur das Argument für die DELETEMIN Operation gezeigt, die DELETEMAX Operation kann analog behandelt werden. Sei I ein Intervall Heap. Wenn die Wurzel von I die L-node ist, beschränkt sich die DELETEMIN Operation auf das Löschen des Minimums aus der Wurzel. Sei nun die L-node von I nicht die Wurzel und [a, b] das Intervall in der Wurzel. Dann ist M IN = a und die DELETEMIN Operation kann wie folgt ausgeführt werden: Betrachte den zugrundeliegenden Min-Heap von I: Ersetze a mit den linken Endwert der L-node, dieses sei x. Nun lasse man x den Heap hinabsteigen, wie bei einem normalen Heap, nur muß, sobald man einen neuen Knoten K erreicht, getestet werden, ob K ein gültiges Intervall enthält. Ist dies nicht der Fall, vertauscht man die Endpunkte des Intervalles. Danach fährt man fort, das Element den Min-Heap absteigen zu lassen. Nun ist es klar, das die DELETEMIN Operation einen Zeitbedarf von O(log n) hat. ❏ Theorem 2.4 Intervall Heaps sind eine effiziente implizite Datenstruktur zur Implementation von double-ended Priority Queues, die die MIN und MAX Operationen mit einem Zeitbedarf von O(1) und die übrigen Operationen mit einem Zeitbedarf von O(log n) unterstützt. Aus den oben gegebenen Argumenten ist leicht ersichtlich, das Intervall Heaps derselben Effizienzklasse angehören wie normale Heaps, da sich die Update Operationen auf Operationen auf den zugrundeliegenden Heaps zurückführen lassen. Es bleibt nun noch die Frage nach der Konstruktion einen Intervall Heaps mit n Knoten aus einer Menge mit 2n − 1 oder 2n Elementen. Lemma 2.5 Ein Intervall Heap mit n Knoten kann aus einer Menge von 2n − 1 oder 2n Elementen mit einem Zeitbedarf von O(n) erzeugt werden. 4 Intervall Heaps Beweis: Als erstes werden die Elemente zu zweit zu Knoten zusammengefaßt und in den Knoten dann zu einem gültigen Intervall umsortiert (Zeitbedarf: O(n)). Danach durchläuft man von unten nach oben Stufenweise die Knoten, und lässt in jedem Knoten, der mindestens einen Nachfolger hat, die beiden Elemente des Knotens in den entsprechenden Unterheap durch geeignetes Vertauschen hinabsteigen, also das min-Element in den entsprechenden Unterheap des zugrundeliegenden Min-Heaps und das max-Element in den zugrundeliegenden Max-Heap. Dieser Unterheap wird damit zu einem gültigen Intervall Heap, so daß man, sobald man alle Knoten besucht hat und bei der Wurzel des ganzen Heaps angekommen ist, einen Intervall Heap erzeugt hat. n Im zweiten Schritt werden 2 Knoten besucht. Sei k = log2 (n). Dann ist k die ungefähre Anzahl von Stufen im Heap. Dann werden maximal n4 Knoten in der (k − 1)-ten Stufe besucht, n8 in der (k − 2)-ten Stufe, usw. bis 2nk = 1 in der ersten Stufe des Heaps. Für einen Knoten der (k − i)-ten Stufe sind dann maximal 2i Vertauschungen notwendig, um im Unterheap die Intervall Heapstruktur zu erzeugen. Für die maximale Anzahl t der Vertauschungen (und damit der Elementvergleiche) erhält man: k k X X n 1 t= · (i − 2) < nk · i 2 2i i=2 i=2 k k X X für k≥7 1 1 k ≤ nk · < nk · < nk 2 = n ⇒ O(n) 2 2 i k k i=2 i=2 Insgesamt hat dieser Algorithmus also eine Laufzeit von O(n). ❏ Es gibt noch die Variante der Intervall*Heaps, die im Prinzip Intervall Heaps mit umgekehrter Ordnungsrelation sind. Definition 2.6 Ein Intervall*Heap ist ein Heap der entweder leer ist oder die folgendes Eigenschaften erfüllt (Die Intervall*Heapeigenschaft): 1. Für jeden Knoten v, der nicht die L-node ist, ist I(v) ein Intervall [a, b] (a, b, ∈ X). 2. In der L-node v ist I(v) entweder ein einfacher Wert a (a ∈ X) oder ein Intervall [a, b] (a, b ∈ X). 3. Für zwei Knoten v und w gilt, falls v Nachfolger von w ist, das I(w) ⊆ I(v). 5 Intervall Heaps Sei [a, b] das Intervall der Wurzel eines Intervall*Heaps. Dann sind a und b offensichtlich die Mediane der Menge V . Im Gegensatz zu Intervall Heaps bilden hierbei die linken Intervallenden einen Max-Heap und die rechten Intervallenden einen Min-Heap. Das Erzeugen eines Intervall*Heaps und die Updateoperationen arbeiten offensichtlich nach denselben Prinzipien und in den selben Laufzeitklassen wie die entsprechenden Operationen von Intervall Heaps. Deshalb soll hier auf eine erneute Darstellung und einen erneuten Beweis der Laufzeiten verzichtet werden. 6 Intervall Heaps 3. d -dimensionale Intervall Heaps Hier soll die d -dimensionale Verallgemeinerung von Intervall Heaps betrachtet werden. Das Hauptproblem, das zu betrachten ist, ist die Konstruktion einer impliziten 2d-endigen Priority Queue, die eine Menge V ⊆ X d speichert und die folgenden Operationen gestattet: 1. MINi : bestimme das Element mit der kleinsten i ten Koordinate. 2. MAXi : bestimme das Element mit der größten i ten Koordinate. 3. INSERT: füge einen Wert x ∈ X der Menge V hinzu. 4. DELETEMINi : lösche das Element mit der kleinsten i ten Koordinate. 5. DELETEMAXi : lösche das Element mit der größten iten Koordinate. Es sei im folgenden d ≥ 2. Benötigt wird eine Verallgemeinerung des Intervalls für eine Menge von Punkten W ⊆ X d , wobei |W | ≥ 2d sei. Definition 3.1 Ein d-Intervall definiert durch eine Menge W ⊆ X d von Punkten ist der d-dimensionale Quader, der durch die Hyperflächen H1 bis H2d gegeben wird, die wie folgt definiert sind: 1. H1 ist die 1-Hyperfläche, die durch den Punkt h1 ∈ W , der die kleinste erste Koordinate von allen Punkten aus W hat, gegeben wird, H2 ist die 1-Hyperfläche, die durch einen Punkt h2 ∈ W − {h1 } mit größter erster Koordinate gegeben wird. 2. Für 1 < i ≤ d ist H2i−1 die i-Hyperfläche, die durch einen Punkt h2i−1 ∈ W − {h1 , · · · , h2i−2 } mit kleinster i-ter Koordinate gegeben wird und H2i ist die i-Hyperfläche, die durch einen Punkt h2i ∈ W − {h1 , · · · , h2i−1 } mit größter i-ter Koordinate gegeben wird. Dabei bezeichne eine i-Hyperfläche die Menge aller Punkte H ⊆ X d mit gegebener i-ter Koordinate. Falls |W | = j < 2d, dann kann dieselbe Definition benutzt werden, wobei nur j Hyperflächen definiert sind und der Quader“ nicht komplett geschlos” sen ist. Für endliche Mengen W ⊆ X d lässt sich das zugehörige d -Intervall IW (begrenzt durch die Hyperflächen Hi mit den Randpunkten hi ) offensichtlich mit einem Zeitbedarf von O(d2 ) bestimmen. Man sagt, das W in 7 Intervall Heaps IW enthalten ist, obwohl genau gesagt nur W − {h1 , · · · , h2d } ⊆ IW . Ein d -Intervall wird eindeutig definiert durch die (geordnete) Menge von Randpunkten h1 , · · · , h2d , oder h1 , · · · , hj im Falle eines unvollständigen Intervalls, und wird als [h1 , · · · , h2d ] bzw. [h1 , · · · , hj ] notiert. Definition 3.2 Ein d-dimensionaler Intervall Heap (d-Intervall Heap) ist ein Heap der entweder leer ist, oder die folgenden Bedingungen erfüllt (die d-Intervall Heapeigenschaft): 1. Für jeden Knoten v, der nicht die L-node ist, ist I(v) ein d-Intervall [a1 , · · · , a2d ] (ai ∈ X d , für 1 ≤ i ≤ 2d). 2. Für die L-node v ist I(v) entweder eine Menge von Punkten aus X d mit 1 ≤ |I(v)| < 2d oder ein d-Intervall [a1 , · · · , a2d ] (ai ∈ X d für 1 ≤ i ≤ 2d). 3. Für alle Paare von Knoten v und w gilt, wenn v Nachfolger von w ist, das I(v) ⊆ I(w). Diese Definition ist dieselbe wie die für eindimensionale Intervall Heaps. Ein d -Intervall Heap repräsentiert die Punkte aus X d , die die Intervallgrenzen d Intervalle des Heaps sind, also die Punkte, deren Koordinaten der die Hyperflächen der Intervalle definieren, und, falls die L-node kein d -Intervall enthält, die in der L-node gespeicherte Menge von Punkten. D-Intervall Heaps lassen sich genauso wie eindimensionale Intervall Heaps als implizite Datenstrukturen implementieren, auch wenn die Implementation nicht ganz so einfach ist. Das folgende Lemma folgt sofort aus der Definition: Lemma 3.3 D-Intervall Heaps unterstützen die MINi und MAXi Operationen mit einer Laufzeit von O(d). Lemma 3.4 D-Intervall Heaps unterstützen die INSERT Operation in einer Laufzeit von O(d log n). Beweis: Sei I ein d -Intervall Heap, x ∈ X d ein Punkt, der zu I hinzugefügt werden soll. Wenn I leer ist, oder die L-node mit der Wurzel identisch ist und kein ganzes d -Intervall enthält, wird x trivialerweise in die Wurzel eingesetzt. Betrachte nun den nicht-trivialen Fall, das die L-node v nicht die Wurzel ist. 8 Intervall Heaps Sei w der Vorgänger von v und I(w) = [a1 , · · · , a2d ]. Falls x ∈ I(w), d.h. x ist in dem d -Intervall von w enthalten, dann füge x zu I(v) hinzu und erzeuge aus I(v) ein d -Intervall, wenn I(v) nun 2d Punkte enthält. Dieses bewahrt die d -Intervall Heapeigenschaft. Falls x ∈ / I(w), dann steige in Richtung der Wurzel auf und teste bei jeden Knoten w der besucht wird, ob x ∈ I(s), wobei s der Vorgänger von w sei. (ist w die Wurzel, dann sei I(s) das unendliche d -Intervall X d ). Sei w0 der erste Knoten auf dem Weg zur Wurzel, für den dieses gilt. (Beachte, das w0 wohldefiniert ist, da der Test an der Wurzel immer ein positives Ergebnis hat, und das jeder Test x ∈ I(s) mit einem Zeitbedarf von O(d) ausgewertet werden kann.) Sei I(w0 ) = [a1 , · · · , a2d ], wobei sicher x ∈ I(w0 ) gilt. Nun ersetze man I(w0 ) durch das von der Menge {a1 , · · · , a2d , x} definierte d -Intervall. Die definierenden Randpunkte setzten sich dann aus x und a1 , · · · , a2d ohne einen Punkt at zusammen. Beachte, das at ∈ I(w0 ). Nun benutze man, das in O(1) bestimmt werden kann, unterhalb welches Nachfolgers eines Knotens, der nicht notwendigerweise die Wurzel ist, sich die L-node befindet. Dies geht, wenn man bedenkt, das dafür zwar O(log n) Operationen mit Arrayindizes oder Zeigern benötigt werden, aber eben O(1) (eben keine) Operationen mit Elementen des Heaps, deren Vergleich oder Vertauschen erheblich aufwendiger sein kann, als ein Integer-Vergleich (z.B. bei Zeichenketten). Nun verfolge man den Weg von wo zurück zu der L-node v und suche dabei den ersten Knoten w1 mit at ∈ / I(w1 ). Falls ein solcher Knoten nicht existiert, dann endet man bei v und kann den Punkt einfach zur Menge I(v) hinzufügen. Gilt |I(v)| = 2d, dann erzeuge man aus der Punktmenge der L-node ein d -Intervall. Dies stellt die d -Intervall Heapeigenschaft wieder her und man ist fertig. Falls ein solcher Knoten w1 existiert, dann verfahre man mit w1 und at so wie mit w0 und x. Dies ergibt ein neues d -Intervall in w1 und einen Punkt at0 ∈ I(w1 ). Nun arbeite man nach unten weiter und wiederhole das Verfahren mit at0 , etc., bis man v erreicht. Es bleibt der Fall zu betrachten, wenn I(v) ein ganzes d -Intervall ist. Dann erzeuge man den nächsten Knoten u der Heapstruktur und initialisiere I(u) als leere Menge. Nun beginnt man in u mit derselben Prozedur wie oben. Dies erhält ebenfalls die d -Intervall Heap Eigenschaft und erzeugt einen gültigen d -Intervall Heap, der nun auch x enthält. Offensichtlich benötigt das Verfahren O(log n) Schritte mit O(d) Kosten, also insgesamt einen Zeitbedarf von O(d log n). ❏ 9 Intervall Heaps Lemma 3.5 D-Intervall Heaps unterstützen die DELETEMINi und DELETEMAXi Operationen in einem Zeitbedarf von O(d2 log n). Beweis: Wie beim eindimensionalen Fall soll das Argument hier nur für die DELETEMINi Operationen gezeigt werden. Die DELETEMAXi Operationen arbeiten analog. Sei I ein d -Intervall Heap. Falls die L-node v die Wurzel ist, dann besteht die DELETEMINi Operation daraus, den Punkt mit der kleinster i-ten Koordinate aus der Menge I(v) zu löschen. Sei nun die Wurzel nicht die L-node von I und [a1 , · · · , a2d ] das d -Intervall der Wurzel. Sicherlich ist MINi der Punkt aj ∈ {a1 , · · · , a2d } mit kleinster i-ter Koordinate (beachte, das dies nicht notwendigerweise der Punkt a2i−1 sein muß). Sei nun MINi = aj . Im wesentlichen muß man jetzt aj löschen und seinen Platz wieder auffüllen, dieses ist aber aufwendiger als im eindimensionalen Fall. Die Nachfolger der Wurzel seien u und v. Betrachte das Verfahren zur Erzeugung von d -Intervallen: Klar ist, das a1 , · · · , aj−1 genau dieselben Punkte sind wie vorher, aber aj hinterläßt ein Loch. Der Punkt mit extremer j-ter Koordinate (es kann das Minimum genauso wie das Maximum gesucht sein!), der dieses Loch füllt, kann einer der Punkte aus I(u) oder I(v) sein, aber auch einer der Punkte aj+1 , · · · , a2d . In diesem Fall wird aj durch ein ak (j < k) ersetzt, und man erhält ein Loch weiter hinten in der Liste. Danach muß man aj+1 , · · · , ak−1 nehmen und bestimmt den Ersatz für ak auf dieselbe Art und Weise. Letztendlich wird das Loch dann aber mit einem Element aus I(u) oder I(v) gefüllt. Beachte, das man O(d) Schritte mit O(d) Kosten benötigt, um diese Konstruktion durchzuführen. Das resutierende d -Intervall umschließt sowohl I(u) als auch I(v). Nun ist es klar, daß das Verfahren mit den Knoten, dem das Element entnommen wurde, iteriert werden muß, solange bis der Knoten keinen Nachfolger mehr hat. Wenn dieser Knoten die L-node ist, dann ist man fertig, sonst muß man einen beliebigen Punkt aus der L-node entfernen und mit dem Verfahren von Lemma 3.4 in den Knoten einfügen. Dieses erzeugt aus I mit einem Zeitbedarf von O(d2 log n) wieder einen gültigen d -Intervall Heap. ❏ Verbleibt die Frage nach der Konstruktion eines d -Intervall Heap aus einer Menge von n Punkten aus X d . 10 Intervall Heaps Theorem 3.6 d-Intervall Heaps können mit einem Zeitbedarf von O(d3 n) aus einer Menge von Punkten aufgebaut werden. Beweis: Als erster werden die Punkte in Gruppen von 2d Punkten zu den Knoten der Heapstruktur zusammengefasst, d.h. aus den jeweils 2d Punkten wird ein d -Intervall erzeugt. Beginnend mit den untersten Knoten wird dann schrittweise ein d -Intervall Heap erzeugt, indem nacheinander, Stufe für Stufe aus jedem Knoten, der kein Blatt ist, und seinen Nachfolgern ein Unterheap erzeugt wird. In einem typischen Schritt wird ein Knoten w, der die Nachfolger u und v hat, die in einen vorhergegangenen Schritt mit ihren Nachfolgern in Unter-d -Intervall Heaps transformiert wurden, mit seinen Nachfolgern zu einem Unter-d -Intervall Heap transformiert. Sei P (x) die Menge der in I(x) gespeicherten Punkte. Dann wird dazu aus den Punkten aus der Menge P = P (w)∪P (u)∪P (v) ein neues d -Intervall erzeugt, indem die entsprechenden Punkte nacheinander ausgewählt und aus P gelöscht werden. Wird ein Punkt aus P (u) oder P (v) gewählt, dann wird dieser Punkt sofort nach dem Verfahren aus dem obigen Lemma aus dem entsprechenden Unter d -Intervall Heap gelöscht, und der Punkt, der stattdessen in P (u) (bzw. P (v)) aufsteigt, zu der Menge P hinzugefügt. Nachdem so ein neues d -Intervall I(w)0 erzeugt wurde, wird es in w gespeichert. Dabei wurden i Punkte aus P (u) und j Punkte aus P (v) benutzt. Offensichtlich gilt i + j ≤ 2d. Anschließend werden i von den i + j Punkten aus I(w), die nicht in I(w)0 enthalten sind, dem Unterheap mit Wurzel u und j dem Unterheap mit Wurzel v hinzugefügt. Für einen Knoten benötigt man damit maximal 2d Schritte mit O(d2 ·Höhe(w)) Kosten zum Löschen der Elemente und genau soviele Schritte mit O(d2 · Höhe(w)) Kosten zum Einfügen der neuen Elemente, wobei Höhe(w) die Anzahl der Stufen unter dem Knoten w sei. Insgesamt hat ein Knoten damit Kosten von O(d3 · Höhe(w)), also folgt mit den selben Argumenten wie im eindimensionalen Fall, das der Algorithmus eine Komplexität von O(d3 · n) hat. ❏ 11 Intervall Heaps 4. Anwendungen von Intervall Heaps Hier werden zwei Anwendungen für Intervall Heaps betrachtet. In der üblichen Implementation als Array wächst und schrumpft ein Intervall Heap am rechten Ende, also an der L-node, wenn Elemente eingefügt oder gelöscht werden. Es kann sinnvoll sein, den Intervall Heap so zu implementieren, das er am linken Ende schrumpft, wenn die DELETEMIN Operation ausgeführt wird, und am rechten Ende schrumpft, wenn die DELETEMAX Operation ausgeführt wird. Dieses lässt sich z.B. beim double Heapsort einsetzen, die offensichtliche Modifikation des Heapsorts, bei der das Array sortiert wird, indem gleichzeitig (i.allg. abwechselnd) am niedrigwertigen und am hochwertigen Ende gearbeitet wird. Für diese Anwendung ist der Intervall Heap eine einfache Lösung in folgender Bedeutung: Das Array mit den zu sortierenden Elementen enthalte 2n Werte. Das umwandeln dieses Arrays in einen Intervall Heap mit n Knoten benötigt einen Zeitbedarf von O(n), wobei der linke Endpunkt des Intervalls eines Knoten i an der Arrayposition n − i und der rechte an Position n − 1 + i (1 ≤ i ≤ n) zu finden ist. Da sich DELETEMIN und DELETEMAX Operationen beim double Heapsort abwechseln, schrumpft der Intervall Heap bei jedem Schritt am richtigen Ende. Dieses macht den double Heapsort zu einem effizienten Sortieralgorithmus für Arrays, der, bezogen auf die Komplexität der Löschoperationen, vergleichbar mit dem Heapsort ist. Eine interressantere Anwendung betrifft die Theorie der mehrdimensionalen Datenstrukturen und die computational geometry“. Es soll das complemen” ” tary-range query“ Problem betrachtet werden, welches wie folgt definiert ist: Gegeben sei eine Menge V von n Punkten im d-dimensionalen Raum und ein d-Intervall B. Bestimme die Punkte von V , die nicht in B enthalten sind. Es lässt sich zeigen, das sich dieses Problem mit Hilfe der d -dimensionalen Intervall Heaps lösen lässt, und zwar mit einem Zeitaufwand von O(d2 n) zum Erzeugen der Datenstruktur und O(d3 K) für eine Anfrage, wobei K die Anzahl der Punkte im Ergebnis ist. Hier soll nur die 1-dimensionale Variante betrachtet werden, dann lautet das Problem wie folgt: Gegeben ist eine Mengen V von n Punkten auf der reellen Zahlengeraden und ein Intervall [x, y], bestimme alle Punkte von V , die nicht im Intervall enthalten sind. In der dynamischen Variante ist ein Algorithmus (und eine Datenstruktur) gesucht, die auch dann effizient ist, wenn Punkte eingefügt oder gelöscht werden können. 12 Intervall Heaps Theorem 4.1 Das (dynamische) 1-dimensionale complementary-range query Problem kann mit einem Intervall Heap mit einem Zeitbedarf von O(n) zum Erzeugen und einem Zeitbedarf von O(K) für eine Anfrage gelöst werden, wobei K die Anzahl der Punkte ist, die die Anfrage zurück gibt. Beweis: Als erstes werden die Punkte in einem Intervall Heap organisiert. Dies lässt sich nach Abschnitt 2 in O(n) bewältigen. Nun soll gezeigt werden, das complementary-range queries in O(K) beantwortet werden können. Sei [x, y] das Anfrageintervall. Der Anfragealgorithmus beginnt an der Wurzel des Intervall Heaps und arbeitet rekursiv in der folgenden Weise, sobald ein Knoten v erreicht wird. Wird ein Knoten v erreicht, dann sind zwei Fälle möglich, wenn I(v) mit [x, y] verglichen wird: Fall i): I(v) ⊆ [x, y]. In diesem Fall muß kein Punkt aus v oder dem Unterheap mit Wurzel v zurückgegeben werden. Der Algorithmus ignoriert den gesamten Unterheap und fährt mit dem nächsten Knoten fort. Fall ii): I(v) ∩ [x, y] ⊆ I(v). In diesem Fall enthält I(v) mindestens einen Punkt der nicht im Intervall [x, y] enthalten ist und zurückgegeben werden muß. Wenn der andere Endpunkt von I(v) auch nicht in [x, y] enthalten ist, dann muß er ebenfalls zurückgegeben werden. Wenn v kein Blatt ist, dann besucht der Algorithmus als nächstes die Blätter von v. Der Anfrage Algorithmus wird also als ein preorder - Durchlauf von I implementiert, wobei Unterbäume, die keine Ergebnisse enthalten, abgeschnitten werden (Fall i)). Die Komplexität des Anfragealgorithmus von O(K) erschließt sich mit den folgenden Argumenten: Der Algorithmus ist linear in der Anzahl der Knoten, die besucht werden. Wenn Fall ii) in einem Knoten eintritt, entstehen Kosten für die ein oder zwei Punkte, die zurückgegeben werden müssen. Wenn Fall i) in einem Knoten v eintritt, dann muß Fall ii) in dem Vorgänger von v eingetreten sein. Deshalb können die Kosten, die durch den Besuch von v entstehen, mit den Kosten, die beim Vorgänger von v entstehen, verrechnet werden. Das kein Knoten mehr als 2 Nachfolger hat, kostet kein gefundener Punkt mehr als O(1), und daraus folgt die Komplexität von O(K). ❏. Zu beachten ist, das ein Intervall Heap nur im folgenden Sinne dynamisch ist: Ein Intervall Heap unterstützt das Einfügen von Objekten mit einem 13 Intervall Heaps Zeitbedarf von O(log n), aber das Löschen von Objekten arbeitet nur dann in derselben Laufzeitklasse, wenn die Position des zu löschenden Objektes im Intervall Heap bekannt ist (und dies dürfte recht selten der Fall sein, zumindest wenn der Intervall heap als Array implementiert wurde, denn dann kann die Information nach der ersten Einfüge- oder Löschoperation schon falsch sein). Das d -dimensionale range-query Problem lässt sich mit einem d -dimensionalen Intervall Heap lösen, darauf soll hier aber nicht weiter eingegangen werden. Ein Anderes Problem ist das 1-dimensionale range query“ Problem: ” Gegeben sein eine Menge V mit n Punkten und ein Intervall [x, y], bestimme alle Punkte von V , die im Intervall liegen. Es ist wesentlich schwerer, für dieses Problem eine dynamische implizite Datenstruktur zu entwerfen, die in linearer Zeit aufgebaut werden kann und Anfregen in O(K) unterstützt. Hier sei nur erwähnt, das man dieses unter der Vorraussetzung, das der Median von V in [x, y] enthalten ist, mit einen ganz ähnlichen Algorithmus wie bei dem des complementary-range query Problems mit Intervall*Heaps lösen kann. 14 Intervall Heaps 5. Implementation & Meßwerte 5.1. Implementation Als erstes ist festzuhalten, das es verschiedene Möglichkeiten gibt, einen Intervall Heap zu implementieren. Als erstes sei die von Van Leeuwen und Wood vorgeschlagene wird Methode genannt (der Intervall Heap): Implementiert ein Array H 1 . . . n2 , wobei jedes Element H [i] (1 ≤ i ≤ n2 ) zwei Werte H [i] .min und H [i] .max mit H [i] .min ≤ H [i] .max enthält, wobei H n2 nur den Wert H n2 .min enthält, wenn n eine ungerade Zahl ist. Dabei gilt: • H 2i .min ≤ H [i] .min • H 2i .max ≥ H [i] .max Diese Datenstruktur wird auch min-max-pair heap genannt. Eine andere Methode ist die Implementation als sog. twin-heap, wobei ein Array T [1 . . . n] einen twin-heap mit n Elementen repräsentiert. Ein Array T ist ein twin-heap, wenn es die folgenden Bedingungen erfüllt (auch twin-heap Eigenschaft genannt): • T 2i ≤ T [i] für 1 < i ≤ n2 j n n ≥ T j + für 1 < j ≤ n − 2 2 2 2 n n • T [i] ≤ T i + 2 für 1 ≤ i ≤2 (falls existent, sonst T [i] ≤ T 2i + n2 ). Dabei ist T [1] das kleinste Element und T n2 + 1 ist das größte Element. Eine weitere Implementation der twin-heaps ist die sog. diamond deque: Sei D [1 . . . n] ein Array mit n Einträgen. Dann muß D den folgenden Bedingungen genügen: Für jedes ungerade i, 1 ≤ i ≤ n gilt: • T + n • D [i] ≤ min {D [2i + 1] , D [2i + 3]} • D [i + 1] ≥ max {D [2i + 2] , D [2i + 4]} • D [i] ≤ D [i + 1]. Es ist sofort ersichtlich, das die beiden Varianten äquivalent sind, da sie sich nur durch eine einfache Adressumrechnung unterscheiden. Der Intervall Heap 15 Intervall Heaps ist ebenfalls zu der diamond deque (und damit zu den twin-heaps) äquivalent, wenn man folgende Gleichungen betrachtet: H [i] .min = D [2i − 1] und lnm H [i] .max = D [2i] ∀1 ≤ i ≤ 2 Hier wurde die Implementation als diamond-deque gewählt, da sie eine bessere Laufzeit versprach als die Implementation als Intervall Heap und, da die Min- und Maxeinträge eines Knoten nebeneinander im Array liegen, näher am Intervall Heap ist als ein twin-heap. 5.2. Meßwerte Hier werden ein paar ausgewählte Meßwerte des eindimensionalen Intervall Heaps und des d -Intervall Heaps gezeigt, um einen Vergleich der Theoretisch zu erwartenden Laufzeit mit der Realität zu haben. Alle Messungen wurden mit einem Pentium III mit 1,2 Ghz (mit Tualatin Kern, CPUID = 6B1) und 384 MB RAM gemacht. Das verwendete Betriebssystem war Windows XP Home Version 2002 mit Service Pack 2, die verwendete Javaversion war Java 2 Standard Edition Version 1.4.2 05. Die Java Virtual Maschine wurde mit dem Parameter -Xmx180M“ gestartet, ” um sicherzustellen, das 180 MB Speicher für das Programm zur Verfügung stehen. 16 Intervall Heaps Erzeugen eines Intervall Heaps msec 2750 2500 2250 2000 1750 1500 Minimum Mittelwert Maximum 1250 1000 750 500 250 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 * 500000 Objekte Anzahl Objekte Minimum in msec Mittelwert in msec Maximum in msec 500000 1000000 1500000 2000000 2500000 3000000 3500000 4000000 4500000 5000000 5500000 6000000 6500000 7000000 7500000 8000000 8500000 9000000 9500000 10000000 120 250 390 501 631 751 881 991 1112 1232 1372 1482 1603 1732 1843 1983 2093 2223 2353 2454 131 259 396 513 646 774 897 1008 1124 1247 1379 1515 1636 1752 1871 2024 2119 2242 2387 2500 140 271 420 521 681 821 942 1041 1142 1272 1402 1582 1713 1773 1902 2103 2144 2284 2474 2524 Die Messungen geben die Zeiten in msec an, die benötigt wurden, um 500000 Objekte in einen Heap mit der angegebenen Anzahl von Objekten einzufügen. Dabei sind Minimal-, Mittel-, und Maximalwert von 10 Messungen angegeben. 17 Intervall Heaps Einfügen in einen Intervall Heap msec 220 200 180 160 140 120 Minimum Mittelwert Maximum 100 80 60 40 20 0 1 #Objekte 250000 500000 750000 1000000 1250000 1500000 1750000 2000000 2250000 2500000 2750000 3000000 3250000 3500000 3750000 4000000 4250000 4500000 4750000 5000000 5 10 15 20 Mittelwert Minimum Maximum 130 140 150 150 150 150 150 150 160 160 160 160 160 160 160 160 160 170 170 170 137 147 155 156 160 161 162 162 167 169 167 169 168 169 168 168 169 176 176 175 35 * 250000 Objekte 151 160 171 171 171 181 171 181 190 191 190 190 190 190 181 200 190 200 191 191 30 #Objekte 5250000 5500000 5750000 6000000 6250000 6500000 6750000 7000000 7250000 7500000 7750000 8000000 8250000 8500000 8750000 9000000 9250000 9500000 9750000 10000000 35 40 Mittelwert Minimum Maximum 170 170 170 170 160 160 170 170 170 170 170 170 160 170 170 170 170 170 170 170 175 174 174 175 175 175 175 175 175 176 174 174 175 177 183 181 180 183 181 182 210 191 190 190 191 191 191 191 191 191 201 190 191 191 201 200 200 200 200 200 Die Messungen geben die Zeiten in msec an, die benötigt wurden, um 250000 Objekte in einen Intervall Heap mit der angegebenen Anzahl von Objekten einzufügen, an. Da durch die sehr kurzen Zeiten die Messgenauigkeit zu wünschen übrig lies, wurden hier alle Messungen 50 mal wiederholt. In der Tabelle sind jeweils Minimal-, Maximal- und Mittelwert dieser Messungen angegeben. 18 Intervall Heaps Löschen aus einem Intervall Heap msec 2200 2000 1800 1600 1400 1200 Minimum Mittelwert Maximum 1000 800 600 400 200 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 *500000 Objekte #Objekte Mittelwert Minimum Maximum 500000 1000000 1500000 2000000 2500000 3000000 3500000 4000000 4500000 5000000 762 1131 1271 1372 1442 1492 1562 1602 1642 1682 783 1149 1291 1381 1458 1504 1570 1633 1658 1693 811 1212 1322 1392 1472 1512 1603 1722 1682 1712 #Objekte Mittelwert Minimum Maximum 5500000 6000000 6500000 7000000 7500000 8000000 8500000 9000000 9500000 10000000 1693 1723 1773 1792 1823 1843 1872 1892 1893 1922 1707 1758 1797 1806 1832 1859 1913 1903 1926 1938 1723 1833 1853 1822 1843 1883 2003 1913 1943 1983 Die Messungen geben die Zeiten in msec an, die benötigt wurden, um 500000 Objekte aus einen Heap mit der angegebenen Anzahl von Objekten zu löschen. Dabei sind Minimal-, Mittel-, und Maximalwert von 10 Messungen angegeben. Hier wurde nur die DELETE-MIN Operation benutzt, die DELETEMAX Operation sollte identische Messwerte ergeben. 19 Intervall Heaps 1D Complementary Range Query msec 6500 6000 5500 5000 4500 4000 3500 Minimum Mittelwert Maximum 3000 2500 2000 1500 1000 500 0 0 5 10 *500000 Objekte #Objekte Mittelwert Minimum Maximum 0 100000 200000 300000 400000 500000 600000 700000 800000 900000 1000000 0 711 1001 1282 1562 1843 2113 2394 2663 2955 3234 0 725 1004 1293 1571 1853 2134 2419 2706 3007 3264 0 732 1012 1311 1582 1873 2143 2454 2774 3085 3364 15 20 #Objekte Mittelwert Minimum Maximum 1100000 1200000 1300000 1400000 1500000 1600000 1700000 1800000 1900000 2000000 3505 3785 4066 4336 4617 4877 5157 5418 5668 5948 3544 3827 4096 4360 4632 4913 5212 5482 5731 5971 3656 3916 4166 4386 4687 4977 5297 5558 5829 6079 Dargestellt sind die Zeiten in msec, die benötigt wurden, um eine Complementary Range Query, die die angegebene Anzahl von Elemente als Antwort ergab, in einem Intervall Heap mit 2000000 Objekten durchzuführen. Angegeben sind Minimal-, Mittel- und Maximalwert von 10 Messungen. Es ist leicht zu sehen, das die Implementation die aus der Theorie gegebenen Laufzeitverhalten von O(log n) beim Einfügen und Löschen und O(n) beim Erzeugen einhält. Überraschend ist, daß das Einfügen von Elementen erheblich schneller vonstatten geht als das Löschen von Elementen. 20 Intervall Heaps Einfügen in einen d -dimensionalen Intervall Heap msec 1000 900 800 700 600 Minimum Mittelwert Maximum 500 400 300 200 100 0 2 5 10 15 Dimensionen 20 25 30 Dimension Dimension Mittelwert Mittelwert Minimum Maximum Minimum Maximum 2 3 4 5 6 7 8 9 10 11 12 13 14 15 200 240 260 291 331 350 381 400 421 450 481 501 531 551 218 247 273 310 340 364 393 415 442 479 514 532 553 579 261 261 290 330 361 380 410 441 471 511 551 561 571 611 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 590 611 631 651 681 711 731 761 791 811 841 861 901 911 942 605 633 658 678 699 724 750 778 818 850 862 890 914 939 956 641 671 681 701 721 731 761 791 872 892 911 941 951 981 972 Hier ist die Zeit, die benötigt wurde, um 500000 Objekte in einen d -Intervall Heap einzufügen, in Abhängigkeit der Dimension dargestellt. Es wurden 10 Messungen gemacht, von denen jeweils Minimal-, Mittel- und Maximalwert angegeben sind. Die Angabe, das die Laufzeit in Bezug auf die Dimension linear ist, scheint zu stimmen. 21 Intervall Heaps Löschen aus einen d -dimensionalen Intervall Heap msec 30000 27500 25000 22500 20000 17500 Minimum Mittelwert Maximum f(x)=x^2*33+190 15000 12500 10000 7500 5000 2500 0 1 5 Dimension 1 5 10 15 20 25 30 10 Minimum 180 440 771 1132 1523 1952 2453 2984 3535 4116 4747 5377 6109 6860 7651 8472 9333 10224 11136 12077 13049 14040 15062 16103 17205 18377 19588 20819 22101 23373 15 Dimension 20 25 Mittelwert Maximum 187 454 783 1156 1543 2003 2480 3010 3570 4146 4807 5410 6160 6943 7705 8560 9404 10326 11236 12166 13158 14164 15185 16224 17370 18518 19754 20978 22280 23581 200 480 832 1242 1582 2163 2553 3124 3705 4216 5017 5518 6359 7140 7891 8733 9594 10485 11407 12338 13309 14320 15332 16354 17545 18647 19909 21131 22382 23654 30 f (x) = x2 · 33 + 190 223 322 487 718 1015 1378 1807 2302 2863 3490 4183 4942 5767 6658 7615 8638 9727 10882 12103 13390 14743 16162 17647 19198 20815 22498 24247 26062 27943 29890 Hier ist die Zeit, die benötigt wurde, um 50000 Objekte aus einen d -Intervall Heap zu löschen, in Abhängigkeit der Dimension dargestellt. Es wurden 10 Messungen gemacht, von denen jeweils Minimal-, Mittel- und Maximalwert angegeben sind. Hierbei zeigt sich, daß das Laufzeitverhalten in Bezug auf die Dimension etwas besser als O(d2 ) ist (vgl. mit der dunkel lilanen Kurve). 22 Intervall Heaps Erzeugen eines d -Intervall Heaps msec 2500 2250 2000 1750 1500 Minimum Mittelwert Maximum 1250 1000 750 500 250 0 1 5 10 15 20 25 30 Dimensionen Dimensionen Mittelwert Minimum Maximum 1 952 967 1072 2 941 958 981 3 1031 1035 1042 4 1052 1080 1142 5 1101 1115 1161 6 1142 1148 1162 7 1192 1205 1242 8 1252 1264 1302 9 1282 1304 1372 10 1332 1347 1392 11 1382 1397 1462 12 1432 1455 1533 13 1472 1487 1502 14 1522 1533 1562 15 1582 1593 1603 Dimensionen Mittelwert Minimum Maximum 16 1633 1649 1743 17 1663 1682 1763 18 1722 1738 1783 19 1763 1787 1883 20 1813 1841 1903 21 1873 1889 1973 22 1913 1937 2003 23 1973 1990 2073 24 2013 2036 2073 25 2073 2082 2093 26 2123 2145 2233 27 2173 2192 2284 28 2223 2238 2273 29 2263 2285 2333 30 2313 2341 2423 Dargestellt ist die Zeit, die benötigt wurde, um einen d -Intervall Heap mit 1000000 Objekten zu erzeugen, in abhängigkeit von der Dimension d. Es wurden 10 Messungen gemacht, von denen der Minimal-, Mittel- und Maximalwert angegeben sind. 23 Intervall Heaps msec 5000 4500 4000 3500 3000 Minimum Mittelwert Maximum 2500 2000 1500 1000 500 0 1 10 20 #Objekte Mittelwert Minimum Maximum 100000 50 64 160 200000 100 120 191 300000 260 263 270 400000 340 346 351 500000 420 429 441 600000 491 509 521 700000 590 596 611 800000 651 673 711 900000 761 774 821 1000000 831 844 852 1100000 901 915 952 1200000 1001 1005 1012 1300000 1061 1079 1122 1400000 1151 1170 1221 1500000 1231 1249 1271 1600000 1301 1318 1352 1700000 1392 1412 1423 1800000 1462 1490 1543 1900000 1562 1571 1583 2000000 1642 1663 1712 2100000 1703 1723 1743 2200000 1812 1827 1883 2300000 1863 1886 1923 2400000 1933 1954 1993 2500000 1392 1412 1472 24 30 *100000 Objekte 40 50 #Objekte Mittelwert Minimum Maximum 2600000 2153 2178 2274 2700000 1502 1521 1612 2800000 2313 2333 2394 2900000 1582 1602 1663 3000000 2524 2561 2674 3100000 1712 1734 1812 3200000 2634 2665 2754 3300000 1833 1853 1923 3400000 2794 2828 2925 3500000 1942 1965 2033 3600000 3034 3063 3174 3700000 2073 2099 2203 3800000 2123 2143 2213 3900000 2193 2222 2313 4000000 2243 2264 2343 4100000 4105 4135 4237 4200000 2483 2519 2603 4300000 2483 2505 2594 4400000 3595 3618 3675 4500000 2523 2549 2624 4600000 2553 2576 2644 4700000 2664 2707 2814 4800000 2674 2704 2784 4900000 4878 4907 4978 5000000 2934 2967 3074 Intervall Heaps Dargestellt sind die Zeiten, die benötigt wurden, um einen d -Intervall Heap mit der gegebenen Anzahl von Objekten zu erzeugen. Es wurden 10 Messungen gemacht, von denen der Minimal-, Mittel- und Maximalwert angegeben sind. Auffällig ist bei dem ersten dieser beiden Diagramme, daß das Einfügen im Mittel eher linear von der Dimension abhängt und nicht, wie theoretisch für den Worst-Case-Fall zu erwartet, kubisch. Das zweite Diagramm zeigt zumindest ansatzweise den erwarteten linearen Zusammenhang von Zeit und der Anzahl der Elemente. Woher die Spitzen und Einbrüchen kommen weiß ich nicht, da aber alle drei Kurven (Minimal-, Mittel- und Maximalwert) dieselbe Form haben, und auch ein weiterer Meßversuch keine signifikant abweichenden Ergebnisse zeigte, dürften es keine Einflüsse aus Multitasking sein. Ich würde die Ursache im Zusammenspiel der Hardware mit der Java Virtual Maschine und dem Algorithmus vermuten, kann da aber nichts beweisen. Es erscheint mir unwahrscheinlich, daß die Ursache des beobachteten Verhaltens nur im Algorithmus zu suchen ist. Unterschiede Implementation ⇔ Vorschlag Zudem bestehen kleine Unterschiede zwischen der Implementation der d Intervall Heaps und der von van Leeuwen und Wood Vorgeschlagenen Implementation: • In der Implementation ist die L-node der letzte Knoten, der die Menge der Elemente, die kein ganzes d -Intervall ergeben enthält, und nicht existent, falls der letzte Knoten ein ganzes d -Intervall enthält, und nicht der letzte Knoten des Heaps. Da die L-node aber nicht explizit gespeichert wird, ist dies rein eine Frage der Interpretation der Werte Anzahl der Elemente“ und Anzahl der Knoten“. Eine Ausnahme ist ” ” die Löschmethode, die die L-node so Interpretiert, wie von van Leeuwen und Wood vorgeschlagen. • In der Implementation sind Elemente eine Knotens in der Reihenfolge [M in1 , M in2 , . . . , M inn , M ax1 , M ax2 , . . . , M axn ], wobei n die Dimension des d -Intervall Heaps sei und M ini (M axi ) das Element mit der kleinsten (größten) i-ten Koordinate aus dem Knoten, und nicht wie vorgeschlagen, also [M in1 , M ax1 , M in2 , M ax2 , . . . , M inn , M axn ] sortiert. Beide Vorgehensweisen haben ihre Vor- und Nachteile, würde ich diese Algorithmen nochmal implementieren, dann würde ich wahrscheinlich die Vorgeschlagene Reihenfolge wählen. • Der d -Intervall Heaps erzeugende Algorithmus arbeitet etwas anders 25 Intervall Heaps als von van Leeuwen und Wood vorgeschlagen, es schien mir günstiger, die Elemente des neuen Intervalls in w auch aus den Elementen des alten Intervalls von w auszuwählen, zudem werden die Elemente aus u und v gelöscht, sobald sie gewählt wurden. Wird ein Element gelöscht, ist das nachgerückte Element auch ein Kandidat für das Intervall in w. Dies ist notwendig, um einen funktionierenden Algorithmus zu erhalten, diese Notwendigkeit könnte aber auch an meiner oben genannten Abwandlung liegen. Im Theorem 3.6 habe ich meinen Algorithmus vorgeschlagen, und nicht den von van Leeuwen und Wood, die beiden Vorschläge haben dieselbe Laufzeitklasse. • Im Gegensatz zu dem Vorschlag von van Leeuwen und Wood kann die Implementation des d -dimensionalen Algorithmus auch mit einer Dimension arbeiten, ich würde es aber nicht empfehlen, da diese deutlich langsamer ist als die eindimensionale Variante, wenn sie auch in denselben Laufzeitklassen arbeiten. 26 Intervall Heaps 6. Quellenangabe Für die Anfertigung dieser Studienarbeit wurden folgende Quellen benutzt: • J. van Leeuwen and D. Wood, Interval Heaps, The Computer Journal, Vol. 36 No. 3 S. 209-216 (1993) • Jingsen Chen, An Efficient Contruction Algorithm for a Class of Implicit Double-Ended Priority Queues, The Computer Journal, Vol .38 No. 10 S. 818-821(1995) • On the complexity of building an interval heap, Yuzheng Ding and Mark Alen Weiss, Information Processing Letters 50 S. 143-144 (1994) • Vorlesung COP 5536/NTU AD 711R, Advanced Data Structures“ ” University of Florida http://www.cise.ufl.edu/˜sahni/cop5536/ Basiert auf Fundamentals of data structures in C++, by E. Horowitz, S. Sahni, and D. Mehta, W. H. Freeman, 1995. 27 Intervall Heaps Anhang A. Programm Verzeichnis der Programme Beschreibung Parameter Ausgabe Verschiedene Konsole Faktor für die Anzahl der Elemente (2) Konsole Anzahl Tests Konsole Anzahl Tests Konsole Anzahl Tests Konsole Anzahl Tests Konsole Anzahl Tests Konsole Anzahl Dimensionen Konsole Datei Anzahl Tests Konsole Anzahl Tests Anzahl Objekte Konsole Eindimensionale Intervall Heaps IntervallHeap ...Test ...ZeittestCRQ ...ZeittestEinfuegen ...ZeittestErzeugen ...ZeittestLoeschen Die Klasse IntervallHeap Parametergesteuertes Programm zum Intervall Heap Test. Misst die Zeiten, die für complementary-range queries mit Ergebnismengen von 0 bis 2 · 106 Objekten benötigt werden. Misst die Zeiten, die benötigt werden, um 25 · 104 Objekte in einen Intervall Heap mit 0 bis 975 · 104 Objekten einzufügen. Misst die Zeiten, die benötigt werden, um Intervall Heaps mit . 5 · 105 bis 107 Objekten (in 5 · 105 Schritten) zu erzeugen Misst die Zeiten, die benötigt werden, um 5 · 105 Objekte aus einen Intervall Heap mit 5 · 105 bis 10 · 107 Objekten zu löschen. d -dimensionale Intervall Heaps DIntervallHeap ...ZeittestEinfuegen ...ZeittestErzeugenDim ...ZeittestErzeugenAnz ...ZeittestLoeschen ...Test 28 Die Klasse DIntervallHeap Misst die Zeit, die benötigt wird um 5 · 105 Objekte in einen d Intervall Heap mit 2 bis 30 Dimensionen einfügen. Misst die Zeit, die benötigt wird um einen d -Intervall Heap mit 106 Objekten und 1 bis 30 Dimensionen zu Erzeugen. Misst die Zeit, die benötigt wird um einen d -Intervall Heap mit 3 Dimensionen und 25 · 103 bis 5 · 106 Objekten zu Erzeugen. Misst die Zeit, die benötigt wird um 5 · 104 Objekte aus einen d Intervall Heap mit 1 bis 30 Dimensionen zu löschen. Erzeugt 5000 Heaps mit 32 · 103 Objekten und liest zufällig Extremelemente aus, bis der Heap wieder leer ist.