In der Informatik ist die Brodal-Warteschlange eine Heap- / Prioritätswarteschlangenstruktur mit sehr niedrigen Worst-Case -Zeitgrenzen für Einfügungen, Minimumsuche, Zusammenführen (Melden) zweier Warteschlangen und Schlüsselverringerung sowie für Minimumlöschung und allgemeine Löschungen. Sie ist die erste Heap-Variante, die diese Grenzen ohne Amortisation der Betriebskosten erreicht. Brodal-Warteschlangen sind nach ihrem Erfinder Gerth Stølting Brodal benannt. [ 1 ]

Obwohl sie bessere asymptotische Schranken als andere Prioritätswarteschlangenstrukturen aufweisen, sind sie, in den Worten Brodals selbst, „ziemlich kompliziert“ und „in der Praxis nicht anwendbar“. [ 1 ] Brodal und Okasaki beschreiben eine persistente ( rein funktionale ) Version von Brodal-Warteschlangen. [ 2 ]

Definition

Eine Brodal-Warteschlange besteht aus zwei Bäumen und fünf Leitbäumen . Die Definition der Leitbaum -Datenstruktur finden Sie im folgenden Abschnitt. In beiden Bäumen hat jeder Knoten einen Rang , der für spätere Operationen nützlich ist und intuitiv dem Logarithmus der Größe des Teilbaums mit Wurzelknoten entspricht. Wir notieren die Anzahl der Kinder des Knotens mit Rang . Wir verwenden außerdem für die Wurzel des Baums und für die Wurzel des Baums . Zu jedem Zeitpunkt muss jeder Teilbaum mit Wurzelknoten die folgenden fünf Invarianten erfüllen (die später als Invarianten bezeichnet werden ):

  •  Wenn es sich um ein Blatt handelt, dann
  •  : ,
  •  Wenn , dann ,
  • Wir heben hervor , dass
  •  : oder .

Hier wird sichergestellt, dass die Größe des Teilbaums mit Wurzelknoten mindestens exponentiell zum Rang dieses Knotens ist. Außerdem wird die Anzahl der Kinder jedes Rangs für einen gegebenen Knoten beschränkt; dies impliziert, dass alle Knoten den Rang und den Grad in haben .

In a Brodal queue, not every node will have a bigger value than its parent, the nodes vialoating this condition will be called violating nodes. However, we want to keep the number of violating nodes relatively small. To keep track of violating nodes, we create for each node two sets and of nodes larger than . Intuitively, are the nodes larger of with large rank (such that if ), and are the nodes with small rank (). These sets are implemented using doubly linked list meaning they have an order. In particular, all violating nodes added to are added at the front of the list, and all violating nodes added to are inserted next to a node of same rank. We let denote the number of nodes in of rank The and lists fulfill these 5 invariants (we will call the invariants):

  •  :
  •  : If then
  • : If then there exist a node such that
  • :
  • : By denoting , we have: for a certain constant .

Since all nodes have rank in the and , all and are in size .

We also have some invariants of the roots of the trees and : and (called the invariants).

  •  : ,
  • : ,
  • : if , then .

The invariant essentially tells us that if we increase the rank of by one, we have at most new "large" violations (here large means having a high rank) without violating the invariant. On the other hand, the invariant tells us that all violations in are "small", this invariant is true per the definition of . Maintaining the invariants and is not trivial, to maintain these we will use the operation which can be implemented using a guide as defined in the next section. Each time we will call the operation, we will essentially :

  1. Add the new violation to or depending on the rank of that violation.
  2. To avoid and from getting too large, we incrementally do two kinds of transformations:
    1. Moving the sons of to to increase the rank of
    2. Reducing the number of violations in by replacing two violations of rank to one violation of rank

The guide data structure

This definition is based on the definition from Brodal's paper.[3]

Wir gehen von einer Folge von Variablen aus und möchten sicherstellen, dass für einen bestimmten Schwellenwert gilt: Die einzige zulässige Operation ist die Subtraktion, die um mindestens 2 verringert und höchstens um 1 erhöht . Ohne Beschränkung der Allgemeinheit können wir annehmen, dass die Folge um 2 verringert und um 1 erhöht wird.

Wird a um eins erhöht, besteht die Aufgabe des Leitfadens darin, uns mitzuteilen, auf welche Indizes die Änderung angewendet werden muss , um den Schwellenwert einzuhalten. Der Leitfaden darf die Funktion nur bei jeder Erhöhung aufrufen.

Der Leitfaden hat Zugriff auf eine weitere Sequenz, sodass und . Solange nach der Erhöhung von gilt , benötigen wir keine Hilfe vom Leitfaden, da „weit“ unter liegt . Wenn jedoch vor der Erhöhung gilt, dann gilt nach der Änderung .

Um die Erklärung zu vereinfachen, können wir annehmen, dass , sodass . Der Leitfaden erzeugt Blöcke in der Sequenz der Form , wobei wir zulassen, dass kein vorkommt . Der Leitfaden gewährleistet die Invariante, dass jedes Element, das sich nicht in einem Block befindet, entweder ein oder ein ist . Hier sind beispielsweise die Blöcke für eine Sequenz von .

Der Leitfaden besteht aus 3 Arrays  :

  • die Anordnung von
  • die Anordnung von
  • Ein Array von Zeigern, wobei alle Zeiger, die sich im selben Block befinden, auf dieselbe Speicherzelle verweisen, die einen Wert enthält. Befindet sich ein Zeiger nicht in einem Block, verweist er auf eine Speicherzelle, die den Wert enthält .

Gemäß dieser Definition besitzt ein Reiseführer zwei wichtige Eigenschaften:

  1. Für jedes Element in einem Block können wir das am weitesten links stehende Element des Blocks in der Zeit finden .
  2. Wir können einen Block in der Zeit zerstören , indem wir der Speicherzelle, auf die jedes Element des Blocks zeigt, einen Wert zuweisen.

Auf diese Weise kann der Guide entscheiden, welche Indizes im Laufe der Zeit aktualisiert werden sollen . Hier ist ein Beispiel:

Um die Blöcke wiederherzustellen, zeigen die Zeiger der 1 und 0, die dem ersten Block hinzugefügt wurden, nun auf dieselbe Zelle wie alle anderen Elemente des ersten Blocks, und der Wert der Zelle des zweiten Blocks wird geändert . Im vorherigen Beispiel waren nur zwei Operationen nötig; dies trifft tatsächlich auf alle Instanzen zu. Daher benötigt die Warteschlange nur Operationen, um die Eigenschaft wiederherzustellen.

Betriebsabläufe einer Brodal-Warteschlange

Um die verschiedenen Prioritätswarteschlangenoperationen zu implementieren , müssen wir zunächst einige grundlegende Transformationen für die Bäume beschreiben.

Transformationen

Verbindungsbäume

Um Bäume zu verknüpfen, benötigen wir drei Knoten gleichen Rangs. Wir können das Minimum dieser drei Knoten mit zwei Vergleichen berechnen. Hier nehmen wir an, dass der Knoten das Minimum ist, aber das Verfahren ist für alle Knoten analog . Wir können nun die Knoten und die beiden linken Söhne von verknüpfen und den Rang von um eins erhöhen . Dadurch bleiben alle Invarianten erhalten .

Entkopplung von Bäumen

Hat der Baum genau zwei oder drei Söhne vom Rang , können wir diese Söhne entfernen und erhalten den Rang seines neuen größten Sohnes plus eins. Aus der Bedingung wissen wir, dass die Invariante erhalten bleibt. Somit bleiben alle Invarianten und erfüllt. Hat der Baum vier oder mehr Kinder, können wir einfach zwei davon entfernen, und alle Invarianten bleiben gültig. Daher führt die Entkopplung eines Baumes vom Rang stets zu zwei oder drei Bäumen vom Rang (durch das Entfernen der zwei oder drei Kinder) und höchstens einem zusätzlichen Baum vom Rang .

Die Söhne einer Wurzel erhalten

Beim Hinzufügen und Entfernen von Söhnen einer Wurzel soll die Invariante erhalten bleiben. Dazu verwenden wir vier Leitfunktionen, zwei für jede Wurzel und . Um in konstanter Zeit auf den Sohn von zugreifen zu können, erstellen wir ein erweiterbares Array von Zeigern, das für jeden Rang einen Zeiger auf einen Sohn von Rang enthält . Eine Leitfunktion stellt sicher, dass gilt, die andere stellt sicher, dass beides für gilt . Die Söhne von Rang und werden auf einfache Weise separat behandelt, um ihre Anzahl zwischen 2 und 7 zu halten. Die entsprechende Variable in der Definition der Leitfunktion enthält die Werte für die obere Schranke und für die untere Schranke.

In diesem Kontext erhöhen wir beim Hinzufügen eines Kindes vom Rang n zur Wurzel den Rang n um eins und wenden die Operationen an. Die Operation besteht hier darin, drei Bäume vom Rang n zu verknüpfen, wodurch ein neues Kind vom Rang n entsteht . Daher verringern wir den Rang n um drei und erhöhen ihn um eins. Falls diese Erhöhung zu viele Kinder vom Rang n erzeugt oder wir einige dieser Kinder miteinander verknüpfen und dadurch möglicherweise den Rang von n erhöhen , müssen wir die Länge des von den Leitknoten verwalteten erweiterbaren Arrays anpassen.

Das Abschneiden eines Sohnes ist sehr ähnlich, nur dass es sich hier um die Entkopplung eines Baumes handelt.

Für die Wurzel ist die Situation nahezu identisch. Da jedoch garantiert wird, dass das kleinste Element ist, wissen wir, dass wir durch Verknüpfen oder Trennen von Kindern von keine Verletzung erzeugen . Dasselbe gilt nicht für . Das Verknüpfen von Söhnen erzeugt niemals neue Verletzungen, aber das Trennen von Söhnen kann bis zu drei neue Verletzungen erzeugen. Der durch das Trennen verbleibende Baum wird zu einem Sohn von gemacht, wenn sein Rang kleiner als ist , andernfalls wird er zu einem Sohn von . Die neuen Verletzungen mit einem Rang größer als werden zu hinzugefügt . Um die Invarianten der Menge (nämlich und ) zu erhalten, müssen wir sicherstellen, dass der Rang von erhöht wird und dass in diesen Invarianten groß genug gewählt wird.

Reduzierung von Verstößen

Ziel dieser Transformation ist es, die Gesamtzahl potenzieller Verstöße zu reduzieren, also zu verringern .

Wir gehen davon aus, dass zwei potenzielle Verstöße gleichen Ranges vorliegen . Dann ergeben sich mehrere Fälle:

  1. Falls sich einer der Knoten als nicht verletzt herausstellt, entfernen wir ihn einfach aus der entsprechenden Verletzungsmenge.
  2. Andernfalls stellen beide Knoten Verletzungen dar. Aufgrund von wissen wir, dass sowohl als auch mindestens einen Bruder haben. Dann gilt:
    1. Wenn und keine Brüder sind, können wir ohne Beschränkung der Allgemeinheit annehmen, dass , und dann können wir die Teilbäume mit Wurzel und vertauschen . Die Anzahl der Verletzungen kann sich bei diesem Tausch nur verringern.
    2. Ansonsten sind und Brüder eines Knotens, den wir nennen werden .
      1. Falls es mehr als einen Bruder vom Rang gibt , können wir diesen einfach abschneiden und ihn zu einem nicht verletzenden Knoten machen, wie im vorherigen Unterabschnitt beschrieben.
      2. Ansonsten sind sie die einzigen Kinder vom Rang von ..
        1. Falls ja , können wir sowohl den Knoten als auch den Knoten aus dem Netzwerk entfernen und sie, wie im vorherigen Unterabschnitt beschrieben, zu nicht verletzenden Knoten des Netzwerks machen.
        2. Andernfalls schneiden wir ab. Der neue Rang von ist dann eins plus der Rang seines linken Sohnes. Wir ersetzen durch einen Sohn von Rang , der wie im vorherigen Unterabschnitt beschrieben abgeschnitten werden kann. Falls der Ersatz für ein verletzender Knoten vom Rang wird , fügen wir ihn zu hinzu . Schließlich erzeugen wir neue Söhne von wie oben beschrieben.

Zu viele Verstöße vermeiden

Die einzigen Verletzungsmengen, denen wir Verletzungen hinzufügen, sind und . Wie oben beschrieben, werden die Invarianten dieser Mengen mithilfe von Leitsätzen aufrechterhalten. Wenn wir eine Verletzung zu hinzufügen, ergeben sich zwei Fälle:

  1. Wenn genau 6 Verstöße gegen den vorgegebenen Rang vorliegen und es mindestens zwei verletzende Knoten gibt, die keine Söhne von sind , wenden wir die im Leitfaden angegebenen Operationen an.
  2. Wenn mehr als vier Verstöße vorliegen, die Unterpunkte von sind , werden die zusätzlichen Verstöße entfernt und unten verlinkt . Dadurch wird der durch diese Knoten verursachte Verstoß beseitigt, ohne die Anleitung zu beeinträchtigen, die die Unterpunkte von verwaltet .

Bei jeder Prioritätswarteschlangenoperation erhöhen wir den Rang von um mindestens eins, indem wir eine konstante Anzahl von Söhnen von nach verschieben (vorausgesetzt, dass ). Durch die Erhöhung des Rangs von können wir Verletzungen zu hinzufügen, ohne die Invarianten zu beeinträchtigen. Falls und , können wir die größten Söhne von abschneiden , sie mit verbinden und dann einen Sohn von erstellen . Dies erfüllt alle Invarianten. Andernfalls schneiden wir einen Sohn von mit Rang ab , trennen diesen Sohn und fügen die resultierenden Bäume zu hinzu . Falls , wissen wir, dass der Knoten mit dem größten Rang ist, und daher können keine großen Verletzungen erzeugt werden.

Operationen in der Prioritätswarteschlange

MakeQueue

Gibt einfach ein Paar leerer Bäume zurück.

FindMin

Rückgabewerte .

Einfügen

ist nur ein Spezialfall von , wobei es sich um eine Warteschlange handelt, die nur und enthält .

Verschmelzen

Es werden vier Bäume verwendet (zwei für jede Warteschlange). Der Baum mit der kleinsten Wurzel wird zum neuen Baum. Ist dieser Baum auch der Baum mit dem höchsten Rang, können alle anderen Bäume wie zuvor beschrieben hinzugefügt werden. In diesem Fall entstehen keine Knoten mit Fehlern, daher werden keine Transformationen an diesen Knoten vorgenommen. Andernfalls wird der Baum mit dem höchsten Rang zum neuen Baum, und die anderen Bäume werden wie im Abschnitt „Verwalten der Kinder einer Wurzel“ beschrieben hinzugefügt. Haben einige Bäume den gleichen Rang wie der neue Baum , können sie vor dem Hinzufügen getrennt werden. Die entstehenden Fehler werden wie im Abschnitt „Vermeiden zu vieler Fehler“ beschrieben behandelt.

Verringern

wird durch das Element ersetzt . Falls , werden die beiden Knoten vertauscht, andernfalls wird die potenzielle neue Verletzung wie im Abschnitt „Vermeidung zu vieler Verletzungen“ erläutert behandelt.

DeleteMin

Die Laufzeit im ungünstigsten Fall darf maximal sein . Zuerst leeren wir den Baum vollständig , indem wir alle Söhne von in verschieben und anschließend einen Sohn vom Rang 0 von erstellen . Dann wird gelöscht, sodass maximal unabhängige Bäume übrig bleiben. Das neue Minimum wird gefunden, indem die Verletzungsmengen der alten Wurzel und alle Wurzeln der neuen Bäume betrachtet werden. Ist das minimale Element keine Wurzel, kann eine Wurzel aus einem Baum gleichen Rangs mit ihr vertauscht werden. Dadurch entsteht maximal eine Verletzung. Anschließend werden die unabhängigen Bäume durch Verknüpfungs- und Entkopplungsoperationen zu Söhnen des neuen minimalen Elements gemacht. Dies stellt die Invarianten und wieder her . Durch Zusammenführen der und Mengen der neuen Wurzel mit den und Mengen der alten Wurzel erhalten wir eine neue Verletzungsmenge der Größe . Durch maximal verletzungsreduzierende Transformationen können wir die Verletzungsmenge so anpassen, dass sie maximal ein Element jedes Rangs enthält. Diese Menge ist unsere neue und leere Menge. Dadurch werden die Invarianten wiederhergestellt. Außerdem muss ein neuer Guide für die neue Wurzel initialisiert werden .

Löschen

Hierbei bezeichnet das kleinste mögliche Element. kann einfach durch Aufruf von gefolgt von implementiert werden .

Details zur Implementierung

In diesem Abschnitt fassen wir einige Implementierungsdetails für die Brodal-Queue-Datenstruktur zusammen.

In jedem Baum ist jeder Knoten ein Datensatz mit folgenden Feldern:

  • Das dem Knoten zugeordnete Element (sein Wert),
  • Der Rang des Knotens,
  • Zeiger auf die linken und rechten Nachbarknoten,
  • ein Zeiger auf den Vaterknoten,
  • ein Zeiger auf den ganz links stehenden Sohn,
  • Zeiger auf das erste Element des Knotens und Mengen,
  • Zeiger auf das folgende und das vorherige Element in der Verletzungsmenge, zu der der Knoten gehört. Wenn dieser Knoten der erste Knoten der Verletzungsmenge ist oder zu der er gehört, zeigt der vorherige Zeiger auf .
  • ein Array von Zeigern auf Söhne von Rang (mit ),
  • ein ähnliches Array für
  • ein Array von Zeigern auf Knoten in vom Rang (mit ).

Schließlich haben wir 5 Richtlinien: drei zur Aufrechterhaltung der oberen Schranken für und und zwei zur Aufrechterhaltung der unteren Schranken für und .

Aufgrund der großen Anzahl an Zeigern und Mengen, die verwaltet werden müssen, ist die Brodal-Warteschlange extrem schwer zu implementieren. Daher lässt sie sich am besten als rein theoretisches Objekt zur Reduzierung der Zeitkomplexität von Algorithmen wie dem Dijkstra-Algorithmus beschreiben . Die Brodal-Warteschlange wurde jedoch in Scala implementiert (das GitHub- Repository ist hier zu finden: https://github.com/ruippeixotog/functional-brodal-queues ). In seiner Veröffentlichung erwähnt Gerth Stølting Brodal: „Eine wichtige Aufgabe für die weitere Arbeit ist die Vereinfachung der Konstruktion, um sie in der Praxis anwendbar zu machen.“ [ 3 ]

Zusammenfassung der Laufzeiten

Hier sind die Zeitkomplexitäten [ 4 ] verschiedener Heap-Datenstrukturen aufgeführt. Die Abkürzung „ am.“ bedeutet, dass die angegebene Komplexität amortisiert ist; andernfalls handelt es sich um die Worst-Case-Komplexität. Zur Bedeutung von „ O ( f )“ und „ Θ ( f )“ siehe Big-O-Notation . Die Operationsnamen setzen einen Min-Heap voraus.

Betrieb find-min delete-min Verringerungstaste einfügen Verschmelzung provisorischer Haufen [ a ]
Binär [ 4 ]Θ (1) Θ (log  n ) Θ (log  n ) Θ (log  n ) Θ ( n ) Θ ( n )
Schiefe [ 5 ]Θ (1) O (log  n ) am.O (log  n ) am.O (log  n ) am.O (log  n ) am.Θ ( n ) am.
Linke [ 6 ]Θ (1) Θ (log  n ) Θ (log  n ) Θ (log  n ) Θ (log  n ) Θ ( n )
Binomial [ 4 ] [ 8 ]Θ (1) Θ (log  n ) Θ (log  n ) Θ (1) am.Θ (log  n ) [ b ]Θ ( n )
Schiefe Binomialverteilung [ 9 ]Θ (1) Θ (log  n ) Θ (log  n ) Θ (1) Θ (log  n ) [ b ]Θ ( n )
2–3 Haufen [ 11 ]Θ (1) O (log  n ) am.Θ (1) Θ (1) am.O (log  n ) [ b ]Θ ( n )
Bottom-up-Schiefe [ 5 ]Θ (1) O (log  n ) am.O (log  n ) am.Θ (1) am.Θ (1) am.Θ ( n ) am.
Paarung [ 12 ]Θ (1) O (log  n ) am.o (log  n ) am. [ c ]Θ (1) Θ (1) Θ ( n )
Rangpaarung [ 15 ]Θ (1) O (log  n ) am.Θ (1) am.Θ (1) Θ (1) Θ ( n )
Fibonacci [ 4 ] [ 16 ]Θ (1) O (log  n ) am.Θ (1) am.Θ (1) Θ (1) Θ ( n )
Strenge Fibonacci-Folge [ 17 ] [ d ]Θ (1) Θ (log  n ) Θ (1) Θ (1) Θ (1) Θ ( n )
Brodal [ 18 ] [ d ]Θ (1) Θ (log  n ) Θ (1) Θ (1) Θ (1) Θ ( n ) [ 19 ]
  1. Die Heap-Erstellung ist die Operation, die aus einer Sequenz von n unsortierten Elementen einen Heap erzeugt. Sie kann in Θ ( n ) Zeit durchgeführt werden, wenn die Meld-Operation in O (log  n ) Zeit läuft (wobei sich beide Komplexitäten amortisieren lassen). [ 5 ] [ 6 ] Ein anderer Algorithmus erreicht Θ ( n ) für binäre Heaps. [ 7 ]
  2. Für persistente Heaps (die keine Decrease-Key-Operationen unterstützen ) reduziert eine generische Transformation die Kosten von `meld` auf die von ` insert` , während die neuen Kosten von `delete-min` die Summe der alten Kosten von `delete-min` und `meld` sind . [ 10 ] Dadurch läuft `meld` in Θ (1)-Zeit (amortisiert, falls die Kosten von `insert` Θ (1)-Zeit betragen), während `delete-min` weiterhin in O (log  n ) läuft. Angewendet auf schiefe Binomial-Heaps führt dies zu Brodal-Okasaki-Warteschlangen, persistenten Heaps mit optimaler Worst-Case-Komplexität. [ 9 ]
  3. ^ Untere Grenze von [ 13 ] obere Grenze von [ 14 ]
  4. Brodal - Warteschlangen und strikte Fibonacci-Heaps erreichen optimale Worst-Case-Komplexitäten für Heaps. Sie wurden ursprünglich als imperative Datenstrukturen beschrieben. Die Brodal-Okasaki-Warteschlange ist eine persistente Datenstruktur , die dasselbe Optimum erreicht, allerdings wird die Verwendung von Decrease-Keys nicht unterstützt.

Gerth Stølting Brodal

Gerth Stølting Brodal ist Professor an der Universität Aarhus , Dänemark . [ 20 ] Er ist vor allem für die Brodal-Warteschlange bekannt.

Referenzen

  1. ^ a b Gerth Stølting Brodal (1996). Worst-case efficient priority queues. Proc. 7th ACM-SIAM Symposium on Discrete Algorithms, pp. 52–58
  2. ^ Gerth Stølting Brodal und Chris Okasaki (1996). Optimale rein funktionale Prioritätswarteschlangen . Journal of Functional Programming.
  3. ^ a b Brodal, Gerth Stølting (1996). "Worst-Case Efficient Priority Queues" (PDF) .{{cite web}}: CS1 maint: url-status (link)
  4. ^ a b c d Cormen, Thomas H. ; Leiserson, Charles E. ; Rivest, Ronald L. (1990). Einführung in Algorithmen (1. Aufl.). MIT Press und McGraw-Hill. ISBN 0-262-03141-8Die
  5. ^ a b c Sleator, Daniel Dominic ; Tarjan, Robert Endre (Februar 1986). „Self-Adjusting Heaps“ . SIAM Journal on Computing . 15 (1): 52–69 . CiteSeerX 10.1.1.93.6678 . doi : 10.1137/0215004 . ISSN 0097-5397 .  
  6. ^ a b Tarjan, Robert (1983). „3.3. Linke Heaps“. Data Structures and Network Algorithms . S.  38–42 . doi : 10.1137/1.9781611970265 . ISBN 978-0-89871-187-5Die
  7. ^ Hayward, Ryan; McDiarmid, Colin (1991). „Average Case Analysis of Heap Building by Repeated Insertion“ (PDF) . J. Algorithms . 12 : 126–153 . CiteSeerX 10.1.1.353.7888 . doi : 10.1016/0196-6774(91)90027-v . Archiviert vom Original (PDF) am 05.02.2016 . Abgerufen am 28.01.2016 . 
  8. ^ „Binomial Heap | Brilliant Math & Science Wiki“ . brilliant.org . Abgerufen am 30.09.2019 .
  9. ^ a b Brodal, Gerth Stølting; Okasaki, Chris (November 1996), „Optimal purely functional priority queues“, Journal of Functional Programming , 6 (6): 839–857 , doi : 10.1017/s095679680000201x
  10. ^ Okasaki, Chris (1998). „10.2. Strukturelle Abstraktion“. Rein funktionale Datenstrukturen (1. Aufl.). S.  158–162 . ISBN 9780521631242Die
  11. ^ Takaoka, Tadao (1999), Theorie der 2–3-Haufen (PDF) , S. 12
  12. ^ Iacono, John (2000), „Verbesserte obere Schranken für Paarungsheaps“, Proc. 7th Scandinavian Workshop on Algorithm Theory (PDF) , Lecture Notes in Computer Science, Band 1851, Springer-Verlag, S.  63–77 , arXiv : 1110.4428 , CiteSeerX 10.1.1.748.7812 , doi : 10.1007/3-540-44985-X_5 , ISBN  3-540-67690-2
  13. ^ Fredman, Michael Lawrence (Juli 1999). „On the Efficiency of Pairing Heaps and Related Data Structures“ (PDF) . Journal of the Association for Computing Machinery . 46 (4): 473–501 . doi : 10.1145/320211.320214 .
  14. ^ Pettie, Seth (2005). Towards a Final Analysis of Pairing Heaps (PDF) . FOCS '05 Proceedings of the 46th Annual IEEE Symposium on Foundations of Computer Science. S.  174–183 . CiteSeerX 10.1.1.549.471 . doi : 10.1109/SFCS.2005.75 . ISBN  0-7695-2468-0Die
  15. ^ Häupler, Bernhard; Sen, Siddhartha; Tarjan, Robert E. (November 2011). „Rank-Pairing-Heaps“ (PDF) . SIAM J. Computing . 40 (6): 1463–1485 . doi : 10.1137/100785351 .
  16. ^ Fredman, Michael Lawrence ; Tarjan, Robert E. (Juli 1987). „Fibonacci-Heaps und ihre Verwendung in verbesserten Netzwerkoptimierungsalgorithmen“ (PDF) . Journal of the Association for Computing Machinery . 34 (3): 596–615 . CiteSeerX 10.1.1.309.8927 . doi : 10.1145/28869.28874 . 
  17. ^ Brodal, Gerth Stølting ; Lagogiannis, George; Tarjan, Robert E. ( 2012). Strict Fibonacci heaps (PDF) . Proceedings of the 44th symposium on Theory of Computing - STOC '12. S.  1177–1184 . CiteSeerX 10.1.1.233.1740 . doi : 10.1145/2213977.2214082 . ISBN  978-1-4503-1245-5Die
  18. ^ Brodal, Gerth S. ( 1996), „Worst-Case Efficient Priority Queues“ (PDF) , Proc. 7th Annual ACM-SIAM Symposium on Discrete Algorithms , S.  52–58
  19. ^ Goodrich, Michael T .; Tamassia, Roberto (2004). „7.3.6. Bottom-Up Heap Construction“. Data Structures and Algorithms in Java (3. Aufl.). S.  338–341 . ISBN 0-471-46983-1Die
  20. ^ „Website von Gerth Stølting Brodal an der Universität Aarhus“ . Abgerufen am 18. Februar 2016 .