<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
	<id>https://wiki-de.moshellshocker.dns64.de/index.php?action=history&amp;feed=atom&amp;title=Nested_Sets</id>
	<title>Nested Sets - Versionsgeschichte</title>
	<link rel="self" type="application/atom+xml" href="https://wiki-de.moshellshocker.dns64.de/index.php?action=history&amp;feed=atom&amp;title=Nested_Sets"/>
	<link rel="alternate" type="text/html" href="https://wiki-de.moshellshocker.dns64.de/index.php?title=Nested_Sets&amp;action=history"/>
	<updated>2026-05-21T08:05:56Z</updated>
	<subtitle>Versionsgeschichte dieser Seite in Wikipedia (Deutsch) – Lokale Kopie</subtitle>
	<generator>MediaWiki 1.43.8</generator>
	<entry>
		<id>https://wiki-de.moshellshocker.dns64.de/index.php?title=Nested_Sets&amp;diff=749177&amp;oldid=prev</id>
		<title>imported&gt;Bauder24 am 5. Dezember 2022 um 14:15 Uhr</title>
		<link rel="alternate" type="text/html" href="https://wiki-de.moshellshocker.dns64.de/index.php?title=Nested_Sets&amp;diff=749177&amp;oldid=prev"/>
		<updated>2022-12-05T14:15:59Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Neue Seite&lt;/b&gt;&lt;/p&gt;&lt;div&gt;Der Begriff &amp;#039;&amp;#039;&amp;#039;Nested Sets&amp;#039;&amp;#039;&amp;#039; (verschachtelte Mengen) bezeichnet ein Modell zur Abbildung eines [[Baum (Graphentheorie)|Baumes]]  mit Hilfe von [[Menge (Mathematik)|Mengen]], die ineinander verschachtelt sind. Dabei wird die &amp;quot;ist-Kind-von&amp;quot;-Beziehung auf eine &amp;quot;ist-Teilmenge-von&amp;quot;-Beziehung abgebildet. Das Modell wurde ursprünglich im Buch &amp;#039;&amp;#039;SQL for Smarties&amp;#039;&amp;#039; von [[Joe Celko]] vorgestellt. Es wird hauptsächlich im Rahmen von Datenbankanwendungen eingesetzt. Diese Technik ist auch unter dem Namen &amp;#039;&amp;#039;&amp;#039;Modified Preorder Tree Traversal&amp;#039;&amp;#039;&amp;#039; (MPTT) bekannt. Mit Hilfe von Nested Sets erkauft man sich die Möglichkeit, Teilbäume oder den Pfad zur Wurzel mit konstantem Aufwand auslesen zu können zum Preis, beim Ändern des Baumes mit komplexeren Operationen arbeiten zu müssen.&lt;br /&gt;
&lt;br /&gt;
== Klassische Baumstruktur ==&lt;br /&gt;
Der klassische Ansatz zur Implementierung einer Baumstruktur in einer Datenbank ist das &amp;#039;&amp;#039;[[Adjazenzliste|Adjazenzlisten-Modell]]&amp;#039;&amp;#039;. Hierbei wird zu jedem Knoten eine Referenz auf dessen Elternknoten abgelegt. Die Wurzel hat dabei keinen Verweis zu einem Elternknoten (das Feld ist mit NULL belegt); ein Blatt ist ein Knoten, zu dem kein anderer Knoten verweist.&lt;br /&gt;
&lt;br /&gt;
== Baumstruktur als verschachtelte Mengen ==&lt;br /&gt;
Beim &amp;#039;&amp;#039;Nested-Sets-Modell&amp;#039;&amp;#039; wird die Baumstruktur in ineinander verschachtelte Mengen transformiert. Jeder Knoten entspricht einer Teilmenge; jede Teilmenge ist eine Teilmenge aller ihrer Eltern-Mengen. In einer Datenbank können diese verschachtelten Mengen repräsentiert werden, indem für jede Teilmenge zwei Werte bestimmt werden, die die Grenzen dieser Teilmenge bestimmen. Diese Werte werden oft mit &amp;#039;&amp;#039;links&amp;#039;&amp;#039; und &amp;#039;&amp;#039;rechts&amp;#039;&amp;#039; bezeichnet. Der Wert &amp;#039;&amp;#039;links&amp;#039;&amp;#039; ist immer kleiner als &amp;#039;&amp;#039;rechts&amp;#039;&amp;#039;. Beide Werte einer Teilmenge sind größer als der Wert &amp;#039;&amp;#039;links&amp;#039;&amp;#039; ihrer Elternmenge und kleiner als deren Wert &amp;#039;&amp;#039;rechts&amp;#039;&amp;#039;. Die folgende Grafik zeigt einen Baum, der in verschachtelte Mengen transformiert wurde. Die grünen Zahlen an den Rändern einer Menge sind die oben beschriebenen Werte &amp;#039;&amp;#039;links&amp;#039;&amp;#039; an der linken Kante und &amp;#039;&amp;#039;rechts&amp;#039;&amp;#039; an der rechten Kante.&lt;br /&gt;
=== Beispiel ===&lt;br /&gt;
[[Datei:Nestedsets.svg]]&lt;br /&gt;
&lt;br /&gt;
== Operationen ==&lt;br /&gt;
=== Knoten einfügen ===&lt;br /&gt;
Die Teilmenge für den ersten Knoten erhält die Werte 1 für &amp;#039;&amp;#039;links&amp;#039;&amp;#039; und 2 für &amp;#039;&amp;#039;rechts&amp;#039;&amp;#039;. Wird eine weitere Teilmenge für einen neuen Knoten unterhalb eines bestehenden Knotens eingefügt, wird &amp;#039;&amp;#039;rechts&amp;#039;&amp;#039; für die frischgebackene Elternmenge um 2 erhöht. Damit dies möglich ist, muss vorher im gesamten Baum jeder Wert &amp;#039;&amp;#039;links&amp;#039;&amp;#039; oder &amp;#039;&amp;#039;rechts&amp;#039;&amp;#039;, der größer als der ursprüngliche Wert &amp;#039;&amp;#039;rechts&amp;#039;&amp;#039; der neuen Elternmenge ist, ebenfalls um 2 erhöht werden. Die Werte &amp;#039;&amp;#039;rechts&amp;#039;&amp;#039; minus 2 und &amp;#039;&amp;#039;rechts&amp;#039;&amp;#039; minus 1 der Elternmenge werden dann der neu eingefügten Teilmenge als &amp;#039;&amp;#039;links&amp;#039;&amp;#039; und &amp;#039;&amp;#039;rechts&amp;#039;&amp;#039; zugeordnet. Zu beachten ist hierbei, dass, anders als beim herkömmlichen Adjazenzlisten-Modell, die Reihenfolge der Kinder eines Knotens erhalten bleibt. Die soeben beschriebe Vorgehensweise ist äquivalent dazu, neue Knoten immer ans Ende der Liste der Kinder des Elternknotens anzuhängen. Genauso ist es denkbar, eine neue Teilmenge an beliebiger Stelle zwischen den anderen Teilmengen der Elternmenge einzufügen. Dabei müssen dann die Werte &amp;#039;&amp;#039;links&amp;#039;&amp;#039; und &amp;#039;&amp;#039;rechts&amp;#039;&amp;#039; der auf die neu eingefügte Teilmenge folgenden Kinder ebenfalls erhöht werden.&lt;br /&gt;
&lt;br /&gt;
=== Transformieren einer Baumstruktur in verschachtelten Mengen ===&lt;br /&gt;
Eine bereits existierende Baumstruktur kann in verschachtelte Mengen überführt werden, in dem sie [[Tiefensuche|der Tiefe nach durchlaufen]] wird. Dabei werden, beginnend bei 1, die Kanten gezählt. Jedes Mal, wenn ein Knoten betreten wird, wird diesem der Wert des Zählers als &amp;#039;&amp;#039;links&amp;#039;&amp;#039; zugeordnet und der Zähler erhöht. Wenn der Knoten verlassen wird, nachdem alle seine Kinder bearbeitet wurden, wird ihm der Wert des Zählers als &amp;#039;&amp;#039;rechts&amp;#039;&amp;#039; zugeordnet und der Zähler abermals erhöht.&lt;br /&gt;
&lt;br /&gt;
=== Teilbaum entfernen ===&lt;br /&gt;
Um einen vollständigen Teilbaum zu entfernen, werden zunächst die Werte &amp;#039;&amp;#039;links&amp;#039;&amp;#039; und &amp;#039;&amp;#039;rechts&amp;#039;&amp;#039; der Wurzel des Teilbaumes bestimmt. Danach kann dieser mitsamt seinen Teilmengen gelöscht werden, indem alle Knoten gelöscht werden, deren Werte für  &amp;#039;&amp;#039;links&amp;#039;&amp;#039; und &amp;#039;&amp;#039;rechts&amp;#039;&amp;#039; innerhalb dieser Werte liegen oder mit ihnen übereinstimmen. Abschließend müssen noch alle &amp;#039;&amp;#039;links&amp;#039;&amp;#039;-Werte sowie alle &amp;#039;&amp;#039;rechts&amp;#039;&amp;#039;-Werte um die Breite des Teilbaumes verringert werden, die größer als der &amp;#039;&amp;#039;rechts&amp;#039;&amp;#039;-Wert des zu entfernenden Knotens sind; die Breite ist hierbei die Differenz zwischen &amp;#039;&amp;#039;rechts&amp;#039;&amp;#039; und &amp;#039;&amp;#039;links&amp;#039;&amp;#039; dessen Wurzel plus 1.&lt;br /&gt;
&lt;br /&gt;
== Auswertung ==&lt;br /&gt;
=== Anzahl aller Knoten eines Teilbaums ===&lt;br /&gt;
Die Hälfte der Breite eines Teilbaums entspricht der Anzahl der Knoten in diesem Teilbaum inklusive der Wurzel. Somit kann die Anzahl der Knoten im gesamten Baum ermittelt werden, indem der Wert &amp;#039;&amp;#039;rechts&amp;#039;&amp;#039; minus dem Wert &amp;#039;&amp;#039;links&amp;#039;&amp;#039; der Wurzel durch zwei geteilt und (auf-)gerundet wird.&lt;br /&gt;
&lt;br /&gt;
=== Pfad zu einem Knoten ===&lt;br /&gt;
Im Gegensatz zum Adjazenzlistenmodell muss beim Nested-Sets-Modell der Pfad zu einem Knoten nicht rekursiv ermittelt werden. Es genügt, alle Teilmengen zu selektieren, deren &amp;#039;&amp;#039;links&amp;#039;&amp;#039;-Werte kleiner sind und deren &amp;#039;&amp;#039;rechts&amp;#039;&amp;#039;-Werte gleichzeitig größer sind als die des betrachteten Knotens. Werden diese Teilmengen nach ihrem &amp;#039;&amp;#039;links&amp;#039;&amp;#039;-Wert sortiert, entspricht ihre Reihenfolge dem Weg von der Wurzel zum betrachteten Knoten.&lt;br /&gt;
&lt;br /&gt;
=== Alle Knoten eines Teilbaumes ===&lt;br /&gt;
Alle Knoten unterhalb eines gegebenen Knotens können ermittelt werden, indem alle Teilmengen selektiert werden, deren Werte &amp;#039;&amp;#039;links&amp;#039;&amp;#039; und &amp;#039;&amp;#039;rechts&amp;#039;&amp;#039; sich innerhalb der Werte &amp;#039;&amp;#039;links&amp;#039;&amp;#039; und &amp;#039;&amp;#039;rechts&amp;#039;&amp;#039; des bearbeiteten Knotens befinden. Beim Adjanzenzlistenmodell müsste hier ebenfalls rekursiv vorgegangen werden.&lt;br /&gt;
&lt;br /&gt;
=== Alle Blätter eines Teilbaumes ===&lt;br /&gt;
Die Abfrage nach einem kompletten Teilbaum kann leicht so modifiziert werden, dass nur Blätter, also Knoten ohne eigene Kinder, selektiert werden. Hierzu wird bei der Selektion als zusätzliches Kriterium &amp;#039;&amp;#039;rechts&amp;#039;&amp;#039; = &amp;#039;&amp;#039;links&amp;#039;&amp;#039; + 1 verwendet.&lt;br /&gt;
&lt;br /&gt;
=== Tiefensuche ===&lt;br /&gt;
Um alle Knoten des Baumes gemäß einer [[Tiefensuche]] zu enumerieren, reicht bereits ein einfaches SELECT mit Sortierung aus. Und das in beiden Varianten &amp;#039;&amp;#039;preorder&amp;#039;&amp;#039; (Eltern- vor Kind-) sowie &amp;#039;&amp;#039;postorder&amp;#039;&amp;#039; (Kind- vor Elternknoten). Ebenso ist die durchlaufene Reihenfolge der Kindknoten aufgrund der symmetrischen Bedeutung von &amp;#039;&amp;#039;links&amp;#039;&amp;#039; und &amp;#039;&amp;#039;rechts&amp;#039;&amp;#039; durch eine leichte Variation der Sortierbedingung einfach umkehrbar.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
SELECT * FROM tree ORDER BY r;  /* DFS, postorder */&lt;br /&gt;
SELECT * FROM tree ORDER BY l;  /* DFS, preorder */&lt;br /&gt;
SELECT * FROM tree ORDER BY l DESC;  /* DFS, reverse postorder (smallest child last) */&lt;br /&gt;
SELECT * FROM tree ORDER BY r DESC;  /* DFS, reverse preorder (smallest child last) */&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die zusätzliche Bestimmung der Knotentiefe beim Durchlauf ist mit Hilfe eines Self-Joins möglich. Hierbei werden alle Tupel aus zwei Knoten selektiert, bei denen die Werte &amp;#039;&amp;#039;links&amp;#039;&amp;#039; und &amp;#039;&amp;#039;rechts&amp;#039;&amp;#039; des ersten Knotens zwischen den Werten &amp;#039;&amp;#039;links&amp;#039;&amp;#039; und &amp;#039;&amp;#039;rechts&amp;#039;&amp;#039; des zweiten Knotens liegen. Dabei kann die Tiefe jedes Knotens ermittelt werden, in dem gezählt wird, wie oft ein Tupel mit diesem Knoten als erstem Knoten auftritt. Das Ergebnis wird nach dem Wert &amp;#039;&amp;#039;links&amp;#039;&amp;#039; der enthaltenen Knoten sortiert. Diese Abfrage könnte in [[SQL]] beispielsweise so aussehen:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
 SELECT (COUNT(parent.id)-1) AS depth, node.id&lt;br /&gt;
 FROM tree AS node, tree AS parent&lt;br /&gt;
 WHERE node.l BETWEEN parent.l and parent.r&lt;br /&gt;
 GROUP BY node.id ORDER BY node.l;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Bei großen &amp;#039;&amp;#039;Nested Sets&amp;#039;&amp;#039; wäre ein solcher Self-Join nur durch das Anlegen zusätzlicher Indizes auf &amp;#039;&amp;#039;links&amp;#039;&amp;#039; und &amp;#039;&amp;#039;rechts&amp;#039;&amp;#039; laufzeittechnisch überhaupt realisierbar. &lt;br /&gt;
Daher wird in der Praxis häufig ein gemischtes Modell von Adjazenzlisten und &amp;#039;&amp;#039;Nested Sets&amp;#039;&amp;#039; verwendet, zu jedem Knoten also noch zusätzlich der Verweis auf den Elternknoten und die Knotentiefe mit abgelegt. Durch diesen vernachlässigbaren Mehraufwand beim Schreiben erreicht man so effiziente Auswertungsmöglichkeiten für viele vergleichbare Fragestellungen.&lt;br /&gt;
&lt;br /&gt;
== Vor- und Nachteile ==&lt;br /&gt;
* Die Komplexität beim Lesen ist in den meisten Fällen konstant. Beim Adjazenzlistenmodell ist der Aufwand linear abhängig von der Tiefe des bearbeiteten Knotens. Im Tausch ist eine Änderung des Baumes beim Nested-Sets-Modell wesentlich aufwändiger als beim Adjazenzlistenmodell. Somit eignet es sich besser für Strukturen, die nicht häufig modifiziert, aber sehr oft gelesen werden.&lt;br /&gt;
* Die Darstellung als Mengen passt besser in die mengenorientierte Welt der Datenbanken. Mit der Abfragesprache [[SQL]] kann auf Mengen besser operiert werden als auf hierarchischen Strukturen.&lt;br /&gt;
* Das Abfragen der direkten Kinder eines Knotens ist schwierig.&lt;br /&gt;
* Die Reihenfolge der Kinder eines Knotens bleibt erhalten.&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
* [http://www.klempert.de/nested_sets/ &amp;#039;&amp;#039;Jede Menge Bäume – Nested Sets&amp;#039;&amp;#039;] von Arne Klempert&lt;br /&gt;
* [http://ffm.junetz.de/members/reeg/DSP/node11.html#SECTION04340000000000000000 &amp;#039;&amp;#039;Bäume in SQL&amp;#039;&amp;#039;] von Christoph Reeg&lt;br /&gt;
* [https://www.php-resource.de/de/php-tutorials/Das-Nested-Sets-Modell---Baeume-mit-SQL_14117 &amp;#039;&amp;#039;Das-Nested-Sets-Modell – Baeume mit SQL&amp;#039;&amp;#039;] von php-resource.de&lt;br /&gt;
* [http://explainextended.com/2009/09/24/adjacency-list-vs-nested-sets-postgresql &amp;#039;&amp;#039;Adjecency List vs. Nested Set: Postgresql&amp;#039;&amp;#039;] von Explain Extended (englisch)&lt;br /&gt;
* [http://explainextended.com/2009/09/25/adjacency-list-vs-nested-sets-sql-server &amp;#039;&amp;#039;Adjecency List vs. Nested Set: SQL-Server&amp;#039;&amp;#039;] von Explain Extended (englisch)&lt;br /&gt;
* [http://explainextended.com/2009/09/28/adjacency-list-vs-nested-sets-oracle &amp;#039;&amp;#039;Adjecency List vs. Nested Set: ORACLE&amp;#039;&amp;#039;] von Explain Extended (englisch)&lt;br /&gt;
* [http://explainextended.com/2009/09/29/adjacency-list-vs-nested-sets-mysql &amp;#039;&amp;#039;Adjecency List vs. Nested Set: MySQL&amp;#039;&amp;#039;] von Explain Extended (englisch)&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Datenstruktur]]&lt;br /&gt;
[[Kategorie:Graphentheorie]]&lt;/div&gt;</summary>
		<author><name>imported&gt;Bauder24</name></author>
	</entry>
</feed>