Was sind die weniger bekannten, aber nützlichen Datenstrukturen?


795

Es gibt einige Datenstrukturen, die wirklich nützlich sind, aber den meisten Programmierern unbekannt sind. Welche sind sie?

Jeder kennt verknüpfte Listen, Binärbäume und Hashes, aber was ist zum Beispiel mit Überspringlisten und Bloom-Filtern ? Ich würde gerne mehr Datenstrukturen kennenlernen, die nicht so häufig vorkommen, aber wissenswert sind, weil sie auf großartigen Ideen beruhen und die Toolbox eines Programmierers bereichern.

PS: Ich interessiere mich auch für Techniken wie Dancing Links, die die Eigenschaften einer gemeinsamen Datenstruktur geschickt nutzen.

BEARBEITEN : Bitte versuchen Sie, Links zu Seiten aufzunehmen, die die Datenstrukturen detaillierter beschreiben. Versuchen Sie auch, ein paar Worte darüber hinzuzufügen, warum eine Datenstruktur cool ist (wie Jonas Kölker bereits betont hat). Versuchen Sie auch, eine Datenstruktur pro Antwort bereitzustellen . Dadurch können die besseren Datenstrukturen allein aufgrund ihrer Stimmen nach oben schweben.


Antworten:


271

Versuche , auch als Präfixbäume oder Crit-Bit-Bäume bekannt , existieren seit über 40 Jahren, sind aber noch relativ unbekannt. Eine sehr coole Verwendung von Versuchen wird in " TRASH - Eine dynamische LC-Trie- und Hash-Datenstruktur " beschrieben, die einen Trie mit einer Hash-Funktion kombiniert.


12
sehr häufig von Rechtschreibprüfern verwendet
Steven A. Lowe

Burst-Versuche sind auch eine interessante Variante, bei der Sie nur ein Präfix der Zeichenfolgen als Knoten verwenden und ansonsten Listen von Zeichenfolgen in den Knoten speichern.
Torsten Marek

Die Regex-Engine in Perl 5.10 erstellt automatisch Versuche.
Brad Gilbert

Nach meiner Erfahrung sind Versuche schmerzlich teuer, da ein Zeiger im Allgemeinen länger ist als ein Zeichen, was eine Schande ist. Sie sind nur für bestimmte Datensätze geeignet.
Joe

18
Da keine SO-Frage unabhängig vom Thema vollständig ist, ohne dass jemand jQuery erwähnt ... John Resig, der Ersteller von jQuery, hat eine interessante Reihe von Beiträgen zur Datenstruktur, in denen er sich unter anderem mit verschiedenen Trie-Implementierungen befasst: ejohn.org/blog/ überarbeitete-Javascript-Wörterbuch-Suche
Oskar Austegard

231

Bloom-Filter : Bit-Array von m Bits, anfangs alle auf 0 gesetzt.

Um ein Element hinzuzufügen, führen Sie es durch k Hash-Funktionen aus, die Ihnen k Indizes in dem Array geben, die Sie dann auf 1 setzen.

Um zu überprüfen, ob sich ein Element in der Menge befindet, berechnen Sie die k- Indizes und prüfen Sie, ob alle auf 1 gesetzt sind.

Dies gibt natürlich eine gewisse Wahrscheinlichkeit für falsch positive Ergebnisse (laut Wikipedia sind es ungefähr 0,61 ^ (m / n), wobei n die Anzahl der eingefügten Elemente ist). Falsch-Negative sind nicht möglich.

Ein Element zu entfernen , ist unmöglich, aber Sie können implementieren Zählen Bloom - Filter durch Anordnung von ints und Erhöhen / Verringern, dargestellt.


20
Sie vergessen, ihre Verwendung mit Wörterbüchern zu erwähnen :) Sie können ein vollständiges Wörterbuch in einen Bloom-Filter mit etwa 512 KB drücken, wie eine Hashtabelle ohne die Werte
Chris S

8
Google zitiert die Verwendung von Bloom-Filtern bei der Implementierung von BigTable.
Brian Gianforcaro

16
@FreshCode Es ermöglicht Ihnen tatsächlich, billig auf das Fehlen eines Elements in der Menge zu testen , da Sie falsch positive, aber niemals falsch negative Ergebnisse erhalten können
Tom Savage

26
@FreshCode Wie @Tom Savage sagte, ist es nützlicher, wenn nach Negativen gesucht wird. Sie können es beispielsweise als schnelle und kleine Rechtschreibprüfung (in Bezug auf die Speichernutzung) verwenden. Fügen Sie alle Wörter hinzu und versuchen Sie dann, die vom Benutzer eingegebenen Wörter nachzuschlagen. Wenn Sie ein Negativ erhalten, bedeutet dies, dass es falsch geschrieben ist. Dann können Sie eine teurere Prüfung durchführen, um die nächstgelegenen Übereinstimmungen zu finden und Korrekturen anzubieten.
Lacop

5
@ abhin4v: Bloom-Filter werden häufig verwendet, wenn die meisten Anfragen wahrscheinlich eine Antwort mit "Nein" zurückgeben (wie hier), was bedeutet, dass die geringe Anzahl von "Ja" -Antworten mit einem langsameren exakten Test überprüft werden kann. Dies führt immer noch zu einer starken Reduzierung der durchschnittlichen Antwortzeit für Abfragen. Ich weiß nicht, ob Chrome's Safe Browsing das tut, aber das wäre meine Vermutung.
j_random_hacker

140

Seil : Es ist eine Schnur, die billige Voranstellungen, Teilzeichenfolgen, mittlere Einfügungen und Anhänge ermöglicht. Ich habe es wirklich nur einmal benutzt, aber keine andere Struktur hätte ausgereicht. Regelmäßige Prepends für Strings und Arrays waren einfach viel zu teuer für das, was wir tun mussten, und es kam nicht in Frage, alles umzukehren.


Ich habe mir so etwas für meinen eigenen Gebrauch überlegt. Gut zu wissen, dass es bereits woanders implementiert wurde.
Kibbee

15
Es gibt eine Implementierung in der SGI STL (1998): sgi.com/tech/stl/Rope.html
Quark

2
Ohne zu wissen, wie es heißt, habe ich kürzlich etwas sehr Ähnliches für Java geschrieben - die Leistung war ausgezeichnet: code.google.com/p/mikeralib/source/browse/trunk/Mikera/src/…
mikera

Seil ist ziemlich selten: stackoverflow.com/questions/1863440/…
Will

6
Mikeras Link ist abgestanden, hier ist der aktuelle .
aptwebapps

128

Überspringlisten sind ziemlich ordentlich.

Wikipedia
Eine Überspringliste ist eine probabilistische Datenstruktur, die auf mehreren parallelen, sortierten verknüpften Listen basiert und deren Effizienz mit einem binären Suchbaum vergleichbar ist (Auftragsprotokoll n durchschnittliche Zeit für die meisten Operationen).

Sie können als Alternative zu ausgeglichenen Bäumen verwendet werden (unter Verwendung eines probalistischen Ausgleichs anstelle einer strikten Durchsetzung des Ausgleichs). Sie sind einfach zu implementieren und schneller als beispielsweise ein rot-schwarzer Baum. Ich denke, sie sollten in jedem guten Programmierer-Toolchest enthalten sein.

Wenn Sie eine ausführliche Einführung in die Überspringlisten erhalten möchten, finden Sie hier einen Link zu einem Video der Vorlesung des MIT über die Einführung in Algorithmen.

Auch hier ist ein Java - Applet demonstriert Skip-Liste visuell.


+1 Qt verwendet für seine sortierten Karten und Sätze eher Sprunglisten als RB-Bäume. Ja, sie sind geschickt (jedenfalls in imperativen Sprachen).
Michael Ekstrand

2
Redis verwendet Sprunglisten, um "Sortierte Mengen" zu implementieren.
Antirez

Überspringlisten sind wahrscheinlich meine bevorzugte Datenstruktur, wenn ich eine gute Datenstruktur benötige und keine Garantie für die Reihenfolge der Daten habe. Ich möchte eine einfachere Implementierung als andere "ausgeglichene" Datenstrukturen. So eine gute Sache.
Earino

Interessante Randnotiz: Wenn Sie Ihren Überspringlisten genügend Ebenen hinzufügen, erhalten Sie im Wesentlichen einen B-Baum.
Riyad Kalla

92

Raumindizes , insbesondere R-Bäume und KD-Bäume , speichern Geodaten effizient. Sie eignen sich für geografische Kartenkoordinatendaten und VLSI-Orts- und Routenalgorithmen sowie manchmal für die Suche nach dem nächsten Nachbarn.

Bit-Arrays speichern einzelne Bits kompakt und ermöglichen schnelle Bitoperationen.


6
Raumindizes sind auch nützlich für N-Körpersimulationen mit weitreichenden Kräften wie der Schwerkraft.
Justin Peel

87

Reißverschlüsse - Ableitungen von Datenstrukturen, die die Struktur so ändern, dass sie den natürlichen Begriff "Cursor" haben - aktuelle Position. Diese sind wirklich nützlich, da sie garantieren, dass Indikatoren nicht unbegrenzt sind - z. B. im xmonad-Fenstermanager, um zu verfolgen, welches Fenster fokussiert hat.

Erstaunlicherweise können Sie sie ableiten, indem Sie Techniken aus der Analysis auf den Typ der ursprünglichen Datenstruktur anwenden !


2
Dies ist nur bei der funktionalen Programmierung nützlich (in imperativen Sprachen behalten Sie nur einen Zeiger oder einen Index). Außerdem verstehe ich immer noch nicht, wie Reißverschlüsse wirklich funktionieren.
Stefan Monov

4
@Stefan Der Punkt ist, dass Sie jetzt keinen separaten Index oder Zeiger behalten müssen.
Don Stewart

69

Hier sind ein paar:

  • Suffix versucht. Nützlich für fast alle Arten der Zeichenfolgensuche (http://en.wikipedia.org/wiki/Suffix_trie#Functionality ). Siehe auch Suffix-Arrays; Sie sind nicht ganz so schnell wie Suffixbäume, aber viel kleiner.

  • Spreizbäume (wie oben erwähnt). Der Grund, warum sie cool sind, ist dreifach:

    • Sie sind klein: Sie benötigen nur den linken und rechten Zeiger wie in einem Binärbaum (es müssen keine Informationen zu Knotenfarbe oder -größe gespeichert werden).
    • Sie sind (vergleichsweise) sehr einfach zu implementieren
    • Sie bieten eine optimale amortisierte Komplexität für eine ganze Reihe von "Messkriterien" (die Protokollierungszeit ist diejenige, die jeder kennt). Sehenhttp://en.wikipedia.org/wiki/Splay_tree#Performance_theorems
  • Heap-geordnete Suchbäume: Sie speichern eine Reihe von (Schlüssel-, Prio-) Paaren in einem Baum, sodass es sich um einen Suchbaum in Bezug auf die Schlüssel handelt und Heap-geordnet in Bezug auf die Prioritäten. Man kann zeigen, dass ein solcher Baum eine einzigartige Form hat (und nicht immer vollständig links gepackt ist). Mit zufälligen Prioritäten erhalten Sie die erwartete O (log n) Suchzeit IIRC.

  • Eine Nische sind Adjazenzlisten für ungerichtete planare Graphen mit O (1) Nachbarabfragen. Dies ist weniger eine Datenstruktur als vielmehr eine besondere Art, eine vorhandene Datenstruktur zu organisieren. So geht's: Jedes planare Diagramm hat einen Knoten mit höchstens 6 Grad. Wählen Sie einen solchen Knoten aus, fügen Sie seine Nachbarn in die Nachbarliste ein, entfernen Sie ihn aus dem Diagramm und wiederholen Sie den Vorgang, bis das Diagramm leer ist. Wenn Sie ein Paar (u, v) erhalten, suchen Sie in der Nachbarliste von v nach u und in der Nachbarliste von u nach v. Beide haben höchstens 6, also ist dies O (1).

Wenn nach dem obigen Algorithmus u und v Nachbarn sind, haben Sie nicht sowohl u in der Liste von v als auch v in der Liste von u. Wenn Sie dies benötigen, fügen Sie einfach die fehlenden Nachbarn jedes Knotens zur Nachbarliste dieses Knotens hinzu, speichern Sie jedoch, wie viel von der Nachbarliste Sie für eine schnelle Suche durchsuchen müssen.


Der Heap-geordnete Suchbaum wird als Treap bezeichnet. Ein Trick, den Sie damit machen können, besteht darin, die Priorität eines Knotens zu ändern, um ihn an den unteren Rand des Baums zu verschieben, wo er leichter zu löschen ist.
Papierpferd

1
"Der Heap-geordnete Suchbaum wird als Treap bezeichnet." - In der Definition, die ich gehört habe, IIRC, ist ein Treap ein Heap-geordneter Suchbaum mit zufälligen Prioritäten. Sie können je nach Anwendung andere Prioritäten wählen ...
Jonas Kölker

2
Ein Suffix- Trie ist fast, aber nicht ganz dasselbe wie der viel coolere Suffix- Baum , der an seinen Rändern Zeichenfolgen und keine einzelnen Buchstaben aufweist und in linearer Zeit (!) Erstellt werden kann. Auch wenn Suffix-Arrays asymptotisch langsamer sind, sind sie in der Praxis für viele Aufgaben aufgrund ihrer geringeren Größe und weniger Zeiger-Indirektionen häufig viel schneller als Suffix-Bäume. Ich liebe die O (1) Planar Graph Lookup BTW!
j_random_hacker

@j_random_hacker: Suffix-Arrays sind nicht asymptotisch langsamer. Hier sind ~ 50 Codezeilen für die Erstellung linearer Suffix-Arrays: cs.helsinki.fi/u/tpkarkka/publications/icalp03.pdf
Edward KMETT

1
@ Edward Kmett: Ich habe dieses Papier tatsächlich gelesen, es war ein ziemlicher Durchbruch bei der Konstruktion von Suffix-Arrays . (Obwohl bereits bekannt war, dass eine lineare Zeitkonstruktion möglich war, indem ein Suffixbaum "über" verwendet wurde, war dies der erste unbestreitbar praktische "direkte" Algorithmus.) Einige Operationen außerhalb der Konstruktion sind auf einem Suffix-Array jedoch immer noch asymptotisch langsamer, es sei denn, es handelt sich um eine Ökobilanz Tisch ist auch gebaut. Dies kann auch in O (n) erfolgen, aber Sie verlieren dadurch die Größen- und Lokalitätsvorteile des reinen Suffix-Arrays.
j_random_hacker

65

Ich denke, sperrenfreie Alternativen zu Standarddatenstrukturen, dh sperrenfreie Warteschlange, Stapel und Liste, werden oft übersehen.
Sie werden immer relevanter, da die Parallelität eine höhere Priorität erhält und ein viel bewundernswerteres Ziel ist als die Verwendung von Mutexen oder Sperren für das gleichzeitige Lesen / Schreiben.

Hier sind einige Links
http://www.cl.cam.ac.uk/research/srg/netos/lock-free/
http://www.research.ibm.com/people/m/michael/podc-1996.pdf [Links zu PDF]
http://www.boyet.com/Articles/LockfreeStack.html

Mike Actons (oft provokanter) Blog enthält einige hervorragende Artikel über schlossfreies Design und Ansätze


Lock-freie Alternativen sind in der heutigen mehrkernigen, sehr parallelen,
skalierbarkeitssüchtigen

Nun, ein Disruptor macht in den meisten Fällen tatsächlich einen besseren Job.
Deadalnix

55

Ich denke, Disjoint Set ist ziemlich geschickt für Fälle, in denen Sie eine Reihe von Elementen in verschiedene Sets aufteilen und die Mitgliedschaft abfragen müssen. Eine gute Implementierung der Union- und Find-Operationen führt zu amortisierten Kosten, die effektiv konstant sind (umgekehrt zu Ackermnans Funktion, wenn ich meine Datenstrukturklasse korrekt zurückrufe).


8
Dies wird auch als "Union-Find-Datenstruktur" bezeichnet. Ich war beeindruckt, als ich zum ersten Mal in der Klasse der Algorithmen von dieser cleveren Datenstruktur erfuhr ...
BlueRaja - Danny Pflughoeft

Union-Find-Delete-Erweiterungen ermöglichen auch ein Löschen mit konstanter Zeit.
Peaker

4
Ich habe ein Disjoint-Set für meinen Dungeon-Generator verwendet, um sicherzustellen, dass alle Räume über Passagen erreichbar sind :)
Goldenratio

52

Fibonacci-Haufen

Sie werden in einigen der schnellsten bekannten Algorithmen (asymptotisch) für viele grafische Probleme verwendet, z. B. für das Problem des kürzesten Pfades. Der Dijkstra-Algorithmus wird in O-Zeit (E log V) mit Standard-Binärhaufen ausgeführt. Die Verwendung von Fibonacci-Heaps verbessert dies auf O (E + V log V), was eine enorme Beschleunigung für dichte Graphen darstellt. Leider haben sie einen hohen konstanten Faktor, was sie in der Praxis oft unpraktisch macht.


Hoher konstanter Faktor, wie Sie sagten, und laut einem Freund, der es musste, schwer gut umzusetzen. Fianal nicht so cool, aber trotzdem wissenswert.
p4bl0

Diese Leute hier haben sie im Vergleich zu anderen Heap-Arten wettbewerbsfähig gemacht : cphstl.dk/Presentation/SEA2010/SEA-10.pdf Es gibt eine verwandte Datenstruktur namens Pairing Heaps, die einfacher zu implementieren ist und eine ziemlich gute praktische Leistung bietet. Die theoretische Analyse ist jedoch teilweise offen.
Manuel

Aus meiner Erfahrung mit Fibonacci-Heaps habe ich herausgefunden, dass der kostspielige Betrieb von Speicherzuordnungen weniger effizient ist als ein einfacher binärer Heap, der von einem Array unterstützt wird.
Jutky

44

Jeder, der Erfahrung mit 3D-Rendering hat, sollte mit BSP-Bäumen vertraut sein . Im Allgemeinen ist es die Methode, eine 3D-Szene so zu strukturieren, dass sie für das Rendern mit Kenntnis der Kamerakoordinaten und der Peilung verwaltbar ist.

Die binäre Raumpartitionierung (BSP) ist eine Methode zum rekursiven Unterteilen eines Raums in konvexe Mengen durch Hyperebenen. Diese Unterteilung führt zu einer Darstellung der Szene mittels einer Baumdatenstruktur, die als BSP-Baum bekannt ist.

Mit anderen Worten, es handelt sich um eine Methode zum Aufteilen kompliziert geformter Polygone in konvexe Mengen oder kleinere Polygone, die vollständig aus Nichtreflexwinkeln bestehen (Winkel kleiner als 180 °). Eine allgemeinere Beschreibung der Speicherplatzpartitionierung finden Sie unter Speicherplatzpartitionierung.

Ursprünglich wurde dieser Ansatz in 3D-Computergrafiken vorgeschlagen, um die Rendereffizienz zu erhöhen. Einige andere Anwendungen umfassen das Ausführen geometrischer Operationen mit Formen (konstruktive Volumengeometrie) im CAD, die Kollisionserkennung in der Robotik und in 3D-Computerspielen sowie andere Computeranwendungen, bei denen komplexe räumliche Szenen verarbeitet werden.


... und die dazugehörigen Octrees und KD-Bäume.
Lloeki


38

Schauen Sie sich Finger Trees an , besonders wenn Sie ein Fan der zuvor erwähnten rein funktionalen Datenstrukturen sind. Sie sind eine funktionale Darstellung persistenter Sequenzen, die den Zugriff auf die Enden in amortisierter konstanter Zeit sowie die Verkettung und zeitliche Aufteilung in der Größe des kleineren Stücks logarithmisch unterstützen.

Gemäß Originalartikel :

Unsere funktionalen 2-3-Finger-Bäume sind ein Beispiel für eine von Okasaki (1998) eingeführte allgemeine Entwurfstechnik, die als implizite rekursive Verlangsamung bezeichnet wird . Wir haben bereits festgestellt, dass diese Bäume eine Erweiterung seiner impliziten Deque-Struktur darstellen und Paare durch 2-3 Knoten ersetzen, um die für eine effiziente Verkettung und Aufteilung erforderliche Flexibilität bereitzustellen.

Ein Fingerbaum kann mit einem Monoid parametrisiert werden. Die Verwendung unterschiedlicher Monoide führt zu unterschiedlichen Verhaltensweisen für den Baum. Auf diese Weise können Finger Trees andere Datenstrukturen simulieren.



Schauen Sie sich diese doppelte Antwort an , es lohnt sich zu lesen!
Francois G

34

Rund- oder Ringpuffer - wird unter anderem zum Streamen verwendet.


4
Ekelhafterweise gelang es auch, patentiert zu werden (zumindest wenn es für Videos verwendet wurde). ip.com/patent/USRE36801
David Eison

Aufgrund des Lesens des Links glaube ich nicht, dass die Datenstruktur selbst patentiert ist, sondern eine darauf basierende Erfindung. Ich bin damit einverstanden, dass dies definitiv eine sehr wenig genutzte Datenstruktur ist.
Schwerkraft

33

Ich bin überrascht, dass niemand Merkle-Bäume (dh Hash-Bäume ) erwähnt hat.

Wird in vielen Fällen verwendet (P2P-Programme, digitale Signaturen), in denen Sie den Hash einer gesamten Datei überprüfen möchten, wenn Ihnen nur ein Teil der Datei zur Verfügung steht.


32

<zvrba> Van Emde-Boas-Bäume

Ich denke, es wäre nützlich zu wissen, warum sie cool sind. Im Allgemeinen ist die Frage "warum" am wichtigsten zu stellen;)

Meine Antwort ist, dass sie Ihnen O (log log n) Wörterbücher mit {1..n} Schlüsseln geben, unabhängig davon, wie viele der Schlüssel verwendet werden. Genau wie die wiederholte Halbierung O (log n) ergibt, ergibt die wiederholte Quadrierung O (log log n), was im vEB-Baum der Fall ist.


Sie sind aus theoretischer Sicht nett. In der Praxis ist es jedoch ziemlich schwierig, wettbewerbsfähige Leistungen zu erzielen. Das mir bekannte Papier hat sie dazu gebracht, bis zu 32-Bit-Schlüssel ( citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.2.7403 ) gut zu funktionieren, aber der Ansatz wird nicht auf mehr als vielleicht 34-35 Bit oder skaliert so und es gibt keine Umsetzung davon.
Manuel

Ein weiterer Grund, warum sie cool sind, ist, dass sie ein Schlüsselbaustein für eine Reihe von Algorithmen sind, die den Cache nicht kennen.
Edward KMETT


29

Eine interessante Variante der Hash-Tabelle heißt Cuckoo Hashing . Es werden mehrere Hash-Funktionen anstelle von nur 1 verwendet, um Hash-Kollisionen zu behandeln. Kollisionen werden behoben, indem das alte Objekt von dem durch den primären Hash angegebenen Speicherort entfernt und an einen durch eine alternative Hash-Funktion angegebenen Speicherort verschoben wird. Cuckoo Hashing ermöglicht eine effizientere Nutzung des Speicherplatzes, da Sie Ihren Ladefaktor mit nur 3 Hash-Funktionen um bis zu 91% erhöhen können und dennoch eine gute Zugriffszeit haben.


5
Überprüfen Sie, ob das Hopscotch-Hashing schneller ist.
chmike

27

Ein Min-Max-Heap ist eine Variation eines Heaps , der eine Warteschlange mit doppelter Priorität implementiert. Dies wird durch eine einfache Änderung der Heap-Eigenschaft erreicht: Ein Baum wird als min-max-geordnet bezeichnet, wenn jedes Element auf geraden (ungeraden) Ebenen kleiner (größer) ist als alle Kinder und Enkelkinder. Die Ebenen sind ab 1 nummeriert.

http://internet512.chonbuk.ac.kr/datastructure/heap/img/heap8.jpg


Schwierig zu implementieren. Selbst die besten Programmierer können etwas falsch machen.
Finnw

26

Ich mag Cache Oblivious-Datenstrukturen . Die Grundidee besteht darin, einen Baum in rekursiv kleineren Blöcken auszulegen, sodass Caches mit vielen verschiedenen Größen die Vorteile von Blöcken nutzen, die bequem in sie passen. Dies führt zu einer effizienten Nutzung des Cachings für alles, vom L1-Cache im RAM bis hin zu großen Datenblöcken, die von der Festplatte gelesen werden, ohne dass die Besonderheiten der Größe einer dieser Caching-Schichten bekannt sein müssen.


Interessante Transkription von diesem Link: "Der Schlüssel ist das Van-Emde-Boas-Layout, benannt nach der
Baumdatenstruktur

23

Links schiefen rot-schwarze Bäume . Eine deutlich vereinfachte Implementierung von rot-schwarzen Bäumen durch Robert Sedgewick, die 2008 veröffentlicht wurde (~ die Hälfte der zu implementierenden Codezeilen). Wenn Sie jemals Probleme hatten, sich mit der Implementierung eines Rot-Schwarz-Baums zu beschäftigen, lesen Sie diese Variante.

Sehr ähnlich (wenn nicht identisch) zu Andersson Trees.



19

Bootstrapped Skew-Binomial-Haufen von Gerth Stølting Brodal und Chris Okasaki:

Trotz ihres langen Namens bieten sie selbst in einer Funktionseinstellung asymptotisch optimale Heap-Operationen.

  • O(1)Größe, Vereinigung , Einsatz, Minimum
  • O(log n) deleteMin

Beachten Sie, dass die Vereinigung im Gegensatz zu den bekannteren Heaps, die üblicherweise in Lehrbüchern zur Datenstruktur behandelt werden, wie z. B. linken Heaps,O(1) eher O(log n)Zeit als Zeit in Anspruch nimmt . Und im Gegensatz zu Fibonacci-Haufen sind diese Asymptotika eher im schlimmsten Fall als amortisiert, selbst wenn sie dauerhaft verwendet werden!

In Haskell gibt es mehrere Implementierungen .

Sie wurden gemeinsam von Brodal und Okasaki abgeleitet, nachdem Brodal einen imperativen Haufen mit den gleichen Asymptoten gefunden hatte.


18
  • Kd-Trees , eine räumliche Datenstruktur, die (unter anderem) beim Echtzeit-Raytracing verwendet wird, hat den Nachteil, dass Dreiecke, die die verschiedenen Räume schneiden, abgeschnitten werden müssen. Im Allgemeinen sind BVHs schneller, weil sie leichter sind.
  • MX-CIF-Quadtrees speichern Begrenzungsrahmen anstelle beliebiger Punktmengen, indem sie einen regulären Quadtree mit einem Binärbaum an den Rändern der Quads kombinieren.
  • HAMT , hierarchische Hash-Map mit Zugriffszeiten, die aufgrund der beteiligten Konstanten im Allgemeinen O (1) -Hash-Maps überschreiten.
  • Invertierter Index , der in Suchmaschinenkreisen sehr bekannt ist, da er zum schnellen Abrufen von Dokumenten verwendet wird, die verschiedenen Suchbegriffen zugeordnet sind.

Die meisten, wenn nicht alle, sind im NIST Dictionary of Algorithms and Data Structures dokumentiert



17

Nicht wirklich eine Datenstruktur; eher eine Art und Weise dynamisch zugewiesenen Arrays, aber die Optimierung Spaltpuffer in Emacs sind Art von kühlem verwendet.


1
Ich würde das definitiv als Datenstruktur betrachten.
Christopher Barber

Für alle Interessierten ist dies genau die Art und Weise, wie die Document-Modelle (z. B. PlainDocument), die die Swing-Textkomponenten unterstützen, ebenfalls implementiert werden. vor 1.2 Ich glaube, die Dokumentmodelle waren gerade Arrays, was zu einer schrecklichen Einfügeleistung für große Dokumente führte. Sobald sie zu Gap Buffers zogen, war wieder alles in Ordnung mit der Welt.
Riyad Kalla

16

Fenwick Tree. Es ist eine Datenstruktur, um die Summe aller Elemente in einem Vektor zwischen zwei gegebenen Subindizes i und j zu zählen. Die triviale Lösung, die Summe von Anfang an vorab zu berechnen, erlaubt es nicht, ein Element zu aktualisieren (Sie müssen O (n) arbeiten, um Schritt zu halten).

Mit Fenwick Trees können Sie in O (log n) aktualisieren und abfragen, und wie es funktioniert, ist wirklich cool und einfach. Es ist wirklich gut erklärt in Fenwicks Originalarbeit, die hier frei verfügbar ist:

http://www.cs.ubc.ca/local/reading/proceedings/spe91-95/spe/vol24/issue3/spe884.pdf

Sein Vater, der RQM-Baum, ist ebenfalls sehr cool: Er ermöglicht es Ihnen, Informationen über das minimale Element zwischen zwei Indizes des Vektors zu speichern, und er funktioniert auch bei der Aktualisierung und Abfrage von O (log n). Ich unterrichte gerne zuerst das RQM und dann den Fenwick Tree.


Ich fürchte, das ist ein Duplikat . Vielleicht möchten Sie die vorherige Antwort ergänzen?
Francois G

Ebenfalls verwandt sind Segmentbäume, die für alle Arten von Bereichsabfragen nützlich sind.
Dhruvbird



12

Es ist ziemlich domänenspezifisch, aber die Datenstruktur mit halber Kante ist ziemlich ordentlich. Es bietet eine Möglichkeit, über Polygonnetze (Flächen und Kanten) zu iterieren, was in der Computergrafik und in der Computergeometrie sehr nützlich ist.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.