Baum (Graphentheorie)Ein Baum ist in der Graphentheorie ein spezieller Typ von Graph, der zusammenhängend ist und keine geschlossenen Pfade enthält, d. h. ein Graph, mit dem sich eine Monohierarchie modellieren lässt. Je nachdem, ob die Kanten des Baums eine ausgezeichnete und einheitliche Richtung besitzen, lassen sich graphentheoretische Bäume unterteilen in ungerichtete Bäume und gewurzelte Bäume, und für gewurzelte Bäume in Out-Trees, bei denen die Kanten von der Wurzel ausgehen, und In-Trees, bei denen Kanten in Richtung Wurzel zeigen. Ein Baum ist ein Wald mit genau einer Zusammenhangskomponente.[1] DefinitionenEin Baum ist ein zusammenhängender kreisfreier ungerichteter Graph. Die Knoten mit Grad 1 heißen Blätter, die übrigen Knoten heißen innere Knoten. Ein gerichteter Baum ist ein gerichteter Graph, der ein ungerichteter Baum ist, wenn man die Richtungen der Kanten ignoriert. Er ist also ein gerichteter schwach zusammenhängender kreisfreier Graph. Bei vielen Autoren müssen die Richtungen einheitlich von einem Knoten weg oder auf einen Knoten zu orientiert sein. Dafür gibt es aber auch den schärferen Begriff des gewurzelten Baums. Ein gewurzelter Baum ist ein gerichteter von einem Knoten aus stark zusammenhängender kreisfreier Graph. Der den starken Zusammenhang definierende Knoten wird Wurzel genannt. Er hat Eingangsgrad 0 und ist der einzige Knoten mit dieser Eigenschaft. Alle Knoten mit Ausgangsgrad 0 heißen Blätter. Alle Knoten mit positivem Ausgangsgrad heißen innere Knoten. So geht die Definition eines Out-Trees. Werden die Richtungen aller Kanten eines solchen Graphen invertiert, so wird er zu einem In-Tree. Dieser wird ebenfalls als gewurzelter Baum angesehen. Man kann jeden ungerichteten Baum an einem beliebigen Knoten fassen und „schütteln“ – die Schwerkraft gibt allen Kanten eine definierte Richtung von weg, die aus dem ursprünglich ungerichteten Baum einen gewurzelten machen mit als Wurzel. Den Kanten eines ungerichteten Baums kann man verschiedene Richtungen geben und so gerichtete Bäume ableiten. Genau davon sind Out-Trees und ebenso viele sind In-Trees. Entfernt man umgekehrt bei einem gerichteten Baum die Orientierung der Kanten, so erhält man einen ungerichteten Baum. EigenschaftenEin endlicher Graph mit Knoten und Kanten kann durch folgende äquivalente Aussagen als Baum definiert werden:
Im Falle unendlicher Graphen müssen hier die dritte und vierte Bedingung aus der Äquivalenz ausgenommen werden. BeweiseZwischen je zwei Knoten von gibt es mindestens einen Pfad, weil jeder Baum zusammenhängend ist. Gäbe es zwei Knoten von mit mindestens zwei Pfaden, dann gäbe es zwei Knoten und auf diesen Pfaden, deren Pfade keinen gemeinsamen inneren Knoten haben (disjunkte Wege), zum Beispiel und . Dann wäre ein Kreis von im Widerspruch zur Annahme, dass ein Baum ist.
Dies lässt sich mit vollständiger Induktion zeigen. Für , also einen leeren Graphen mit einem einzelnen Knoten und ohne Kanten, gilt . Nach Induktionsvoraussetzung nehmen wir an, dass die Gleichung für jeden Baum mit Knoten gilt. Ist ein Graph mit Knoten und die Knoten eines längsten Pfades von . Alle Nachbarn von liegen auf diesem Pfad, sonst wäre er nicht der längste Pfad. ist der einzige Nachbar von , denn sonst würde einen Kreis enthalten. Entfernen wir und die Kante aus , dann erhalten wir einen zusammenhängenden Graphen, denn ist der einzige Nachbar von . Der entstandene Graph hat genau einen Knoten und eine Kante weniger als , also Knoten. Nach Induktionsvoraussetzung gilt , also hat der entstandene Graph Kanten. Daraus folgt, dass der Graph genau Knoten und Kanten hat.
Wäre nach Entfernen der Kante immer noch zusammenhängend, dann würde der entstandene Graph einen Pfad von nach enthalten und wäre ein Kreis von .
Wäre nach Hinzufügen der Kante immer noch kreisfrei, dann würde keinen Pfad von nach enthalten und wäre nicht zusammenhängend im Widerspruch zur Annahme, dass ein Baum ist. Weitere Eigenschaften
Spezielle BäumeEs existiert eine Vielzahl von Begriffen, die Bäume näher spezifizieren. So gibt es zum Beispiel
Zeichnen von BäumenDie grafische Ausgabe eines Baums ist ein nicht triviales Problem. Allgemein gilt, dass jeder Baum planar, das heißt ohne Überschneidungen der Kanten gezeichnet werden kann. Je nach Anwendungszweck gibt es weitere Wünsche an die Art der Ausgabe:
Es gibt verschiedene Algorithmen, deren Ergebnisse recht verschieden aussehen. Meist lösen sie nur einige, aber nicht alle Wünsche an die Ausgabe. Bekannte Algorithmen sind die HV-Bäume und der Algorithmus von Walker. KombinatorikEs gibt verschiedene bezeichnete Bäume mit Knoten. Diese Aussage ist als Cayley-Formel bekannt. Einen einfachen Beweis liefert der Prüfer-Code, der eine Bijektion zwischen allen möglichen Codes der Länge und allen bezeichneten Bäumen auf Knoten ermöglicht. Wenn die Knoten nicht nummeriert sind, isomorphe Bäume (siehe Isomorphie von Graphen) also nicht mitgezählt werden, verhält sich diese Anzahl asymptotisch wie mit und , wie Richard Otter im Jahr 1948 bewies.[4] Eine genaue mathematische Formel ist nicht bekannt. Die folgende Tabelle zeigt die mit Hilfe eines Computers bestimmten Anzahlen für :[5]
SpannbäumeJeder ungerichtete, zusammenhängende Graph enthält einen ihn aufspannenden Baum als Teilgraphen. Minimale Spannbäume haben eine möglichst kleine Anzahl von Kanten oder eine möglichst kleine Summe der Kantengewichte. Die Berechnung minimaler Spannbäume findet direkte Anwendung in der Praxis, beispielsweise für die Erstellung von kostengünstigen zusammenhängenden Netzwerken, wie beispielsweise Telefonnetzen oder elektrischen Netzen. VerallgemeinerungenWaldEin Wald ist ein ungerichteter Graph, dessen Zusammenhangskomponenten Bäume sind. k-BaumEin ungerichteter Graph heißt -Baum, wenn er wie folgt rekursiv erzeugbar ist:
Ein partieller -Baum entsteht durch die Entfernung von Kanten aus einem -Baum: Ist ein -Baum, so ist mit ein partieller -Baum.[6][7][8][9] Durch die angegebene Definition haben partielle k-Bäume immer mindestens Knoten, was nicht immer wünschenswert ist. Darum gibt es auch die folgende Definition: Eine weitere Eigenschaft ist, dass die Menge der partiellen k-Bäume gleich der Menge der Graphen mit Baumweite höchstens ist.[13][14] ProgrammierungDas folgende Beispiel in der Programmiersprache C# zeigt die Implementierung eines ungerichteten Graphen mit Adjazenzlisten. Der ungerichtete Graph wird als Klasse UndirectedGraph deklariert. Bei der Ausführung des Programms wird die Methode Main verwendet, die auf der Konsole ausgibt, ob der Graph ein Baum ist.[15] using System;
using System.Collections.Generic;
using System.Linq;
// Deklariert die Klasse für die Knoten des Graphen
class Node
{
public int index;
public string value;
public HashSet<Node> adjacentNodes = new HashSet<Node>(); // Menge der Nachbarknoten
}
// Deklariert die Klasse für den ungerichteten Graphen
class UndirectedGraph
{
public HashSet<Node> nodes = new HashSet<Node>();
// Diese Methode verbindet die Knoten node1 und node2 miteinander.
public void ConnectNodes(Node node1, Node node2)
{
node1.adjacentNodes.Add(node2);
node2.adjacentNodes.Add(node1);
}
// Diese rekursive Methode prüft, ob der Graph Zyklen enthält
public bool IsCyclic(Node node, Dictionary<Node, bool> areConnected, Node parentNode)
{
areConnected[node] = true; // Setzt den aktuellen Knoten als durchlaufen
foreach (Node nextNode in node.adjacentNodes) // foreach-Schleife, die alle benachbarten Knoten des aktuellen Knotens durchläuft
{
if (!areConnected[nextNode]) // Wenn der benachbarten Knoten noch nicht durchlaufen wurde
{
if (IsCyclic(nextNode, areConnected, node)) // Rekursiver Aufruf der Methode mit dem benachbarten Knoten als aktuellen Knoten
{
return true; // Wenn der rekursive Aufruf true zurückgibt
}
}
else // Wenn der benachbarten Knoten schon durchlaufen wurde ...
{
if (nextNode != parentNode) // ... und der benachbarte Knoten nicht der Elternknoten ist, bilden die durchlaufenen Knoten einen Zyklus
{
return true;
}
}
}
return false; // Sonst enthält der Graph keinen Zyklus
}
// Diese Methode prüft, ob der Graph ein Baum ist.
public bool IsTree()
{
Dictionary<Node, bool> areConnected = new Dictionary<Node, bool>();
foreach (Node node in nodes) // foreach-Schleife, die alle Knoten des Graphen durchläuft
{
areConnected.Add(node, false); // Setzt alle Knoten als nicht durchlaufen
}
if (IsCyclic(nodes.ElementAt(0), areConnected, null)) // Wenn die Komponente mit dem ersten Knoten Zyklen enthält, false zurückgeben
{
return false;
}
foreach (Node node in nodes) // foreach-Schleife, die alle Knoten des Graphen durchläuft
{
if (!areConnected[node]) // Wenn ein Knoten nicht verbunden ist, dann false zurückgeben
{
return false;
}
}
return true; // Sonst ist der Graph ein Baum
}
}
class Program
{
// Hauptmethode, die das Programm ausführt
public static void Main(string[] args)
{
// Deklariert und initialisiert 5 Knoten
Node node1 = new Node{index = 0, value = "A"};
Node node2 = new Node{index = 1, value = "B"};
Node node3 = new Node{index = 2, value = "C"};
Node node4 = new Node{index = 3, value = "D"};
Node node5 = new Node{index = 4, value = "E"};
// Deklariert und initialisiert ein Array mit den Knoten
Node[] nodes = {node1, node2, node3, node4, node5};
// Erzeugt einen ungerichteten Graphen
UndirectedGraph undirectedGraph = new UndirectedGraph();
int numberOfNodes = nodes.Length;
for (int i = 0; i < numberOfNodes; i++) // for-Schleife, die alle Knoten durchläuft
{
undirectedGraph.nodes.Add(nodes[i]); // Fügt die Knoten dem Graphen hinzu
}
// Verbindet Knoten des Graphen miteinander
undirectedGraph.ConnectNodes(node2, node1);
undirectedGraph.ConnectNodes(node1, node3);
undirectedGraph.ConnectNodes(node1, node4);
undirectedGraph.ConnectNodes(node4, node5);
if (undirectedGraph.IsTree()) // Aufruf der Methode, die prüft, ob der Graph ein Baum ist
{
Console.WriteLine("Der Graph ist ein Baum."); // Ausgabe auf der Konsole
}
else
{
Console.WriteLine("Der Graph ist kein Baum."); // Ausgabe auf der Konsole
}
Console.ReadLine();
}
}
Siehe auchAnmerkungen
Literatur
WeblinksCommons: Baumstrukturen – Sammlung von Bildern, Videos und Audiodateien
Einzelnachweise
|