<?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=Tiefensuche</id>
	<title>Tiefensuche - 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=Tiefensuche"/>
	<link rel="alternate" type="text/html" href="https://wiki-de.moshellshocker.dns64.de/index.php?title=Tiefensuche&amp;action=history"/>
	<updated>2026-06-11T09:31:12Z</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=Tiefensuche&amp;diff=70580&amp;oldid=prev</id>
		<title>imported&gt;YMS: Sprache</title>
		<link rel="alternate" type="text/html" href="https://wiki-de.moshellshocker.dns64.de/index.php?title=Tiefensuche&amp;diff=70580&amp;oldid=prev"/>
		<updated>2026-01-06T23:38:08Z</updated>

		<summary type="html">&lt;p&gt;Sprache&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Neue Seite&lt;/b&gt;&lt;/p&gt;&lt;div&gt;[[Datei:Depth-First-Search.gif|mini|250px|[[Animation]] der Tiefensuche in einem [[Baum (Datenstruktur)|Baum]]]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Tiefensuche&amp;#039;&amp;#039;&amp;#039; ({{enS|depth-first search}}, &amp;#039;&amp;#039;DFS&amp;#039;&amp;#039;) ist in der [[Informatik]] ein Verfahren zum Suchen von [[Knoten (Graphentheorie)|Knoten]] in einem [[Graph (Graphentheorie)|Graphen]]. Sie zählt zu den uninformierten [[Suchalgorithmen]]. Im Gegensatz zur [[Breitensuche]] wird bei der Tiefensuche zunächst ein [[Weg (Graphentheorie)|Pfad]] vollständig in die Tiefe beschritten, bevor abzweigende Pfade beschritten werden&amp;lt;ref&amp;gt;{{Literatur |Autor=Volker Turau |Titel=Algorithmische Graphentheorie |Auflage=3 |Verlag=Oldenbourg Wissenschaftsverlag |Ort=München |Datum=2009 |ISBN=978-3-486-59057-9 |Seiten=94–98}}&amp;lt;/ref&amp;gt;. Dabei sollen alle erreichbaren Knoten des Graphen besucht werden. Für Graphen mit potenziell wenigen, langen Pfaden bietet sich die [[beschränkte Tiefensuche]] an, bei der jeder Pfad nur bis zu einer bestimmten Tiefe beschritten wird.&lt;br /&gt;
&lt;br /&gt;
Eine Verbesserung der Tiefensuche ist die [[iterative Tiefensuche]].&lt;br /&gt;
&lt;br /&gt;
== Arbeitsweise ==&lt;br /&gt;
{{Siehe auch|Binärbaum#Tiefensuche|titel1 = Binärbaum - Tiefensuche}}&lt;br /&gt;
Die Tiefensuche ist ein uninformierter [[Suchalgorithmus]], welche durch Expansion des jeweils ersten auftretenden [[Nachfolger (Graphentheorie)|Nachfolgeknotens]] im [[Graph (Graphentheorie)|Graphen]] nach und nach vom Startknoten aus weiter in die Tiefe sucht. In welcher Reihenfolge die Nachfolger eines Knotens dabei bestimmt werden, hängt von der Repräsentation der [[Nachfolger (Mathematik)|Nachfolger]] ab. Bei der Repräsentation über eine [[Adjazenzliste]] mittels einer [[Verkettete Liste|verketteten Liste]] werden beispielsweise die Knoten in der Reihenfolge ihres Eintrags in dieser [[Liste (Datenstruktur)|Liste]] durchlaufen. Im oben angegebenen Bild wird implizit davon ausgegangen, dass die Nachfolger von links nach rechts ausgewählt werden.&lt;br /&gt;
&lt;br /&gt;
Für [[Ungerichteter Graph|ungerichtete Graphen]] sieht das Verfahren wie folgt aus: Zuerst wird ein Startknoten &amp;lt;math&amp;gt; \left. u \right. &amp;lt;/math&amp;gt; ausgewählt. Von diesem [[Knoten (Graphentheorie)|Knoten]] aus wird nun die erste [[Kante (Graphentheorie)|Kante]] &amp;lt;math&amp;gt; \left( u,v \right) &amp;lt;/math&amp;gt; betrachtet und getestet, ob der gegenüberliegende Knoten &amp;lt;math&amp;gt; \left. v \right. &amp;lt;/math&amp;gt; schon entdeckt wurde bzw. das gesuchte Element ist. Ist dies noch nicht der Fall, so wird [[Rekursion|rekursiv]] für diesen Knoten die Tiefensuche aufgerufen, wodurch wieder der erste [[Nachfolger (Mathematik)|Nachfolger]] dieses Knotens expandiert wird. Diese Art der Suche wird so lange fortgesetzt, bis das gesuchte Element entweder gefunden wurde oder die Suche bei einer [[Senke (Graphentheorie)|Senke]] im [[Graph (Graphentheorie)|Graphen]] angekommen ist und somit keine weiteren Nachfolgeknoten mehr untersuchen kann. An dieser Stelle kehrt der [[Algorithmus]] nun zum zuletzt expandierten Knoten &amp;lt;math&amp;gt; \left. u \right. &amp;lt;/math&amp;gt; zurück und untersucht den nächsten Nachfolger des Knotens. Sollte es hier keine weiteren Nachfolger mehr geben, geht der Algorithmus wieder Schritt für Schritt zum jeweiligen [[Vorgänger (Graphentheorie)|Vorgänger]] zurück und versucht es dort erneut. Ein Beispiel für die Anwendung der Tiefensuche auf einen [[Baum (Graphentheorie)|Baum]] zeigt die [[Animation]].&lt;br /&gt;
[[Datei:Tree edges.svg|mini|Die vier Typen von [[Kante (Graphentheorie)|Kanten]], die vom Startknoten 1 des gezeigten [[Gerichteter Graph|gerichteten Graphen]] definiert werden. Die schwarzen Kanten zeigen den [[Baum (Graphentheorie)|Baum]], den die Tiefensuche durchläuft.]]&lt;br /&gt;
Die [[Kante (Graphentheorie)|Kanten]] des [[Graph (Graphentheorie)|Graphen]], die vom [[Algorithmus]] zum Durchlaufen des Graphen benutzt werden, werden als &amp;#039;&amp;#039;&amp;#039;Baumkanten&amp;#039;&amp;#039;&amp;#039; bezeichnet. Diejenigen Kanten, die nicht benutzt werden und von einem [[Knoten (Graphentheorie)|Knoten]] zu einem anderen Knoten im selben [[Teilbaum]] führen, der bei der Tiefensuche &amp;#039;&amp;#039;später besucht wird&amp;#039;&amp;#039;, heißen &amp;#039;&amp;#039;&amp;#039;Vorwärtskanten&amp;#039;&amp;#039;&amp;#039;. Diejenigen Kanten, die nicht benutzt werden und von einem Knoten zu einem anderen Knoten im selben Teilbaum führen, der bei der Tiefensuche &amp;#039;&amp;#039;bereits vorher besucht wurde&amp;#039;&amp;#039;, heißen &amp;#039;&amp;#039;&amp;#039;Rückwärtskanten&amp;#039;&amp;#039;&amp;#039;. Diejenigen Kanten, die „quer“ von einem Teilbaum zu einem anderen Teilbaum verlaufen, heißen &amp;#039;&amp;#039;&amp;#039;Querkanten&amp;#039;&amp;#039;&amp;#039;. Innerhalb des Tiefensuchbaums würde der [[Pfad (Graphentheorie)|Pfad]] zwischen zwei über eine Querkante verbundenen Knoten zunächst ein Auf- und dann ein Absteigen im [[Baum (Graphentheorie)|Baum]] erfordern. Vorwärtskanten, Rückwärtskanten, Querkanten und Baumkanten ergeben insgesamt die Kantenmenge des Graphen.&lt;br /&gt;
{|&lt;br /&gt;
|[[Datei:DepthFirstSearch graph cities de.svg|mini|350px|links|Eine [[Graphentheoretisch|graphentheoretische]] Landkarte von [[Deutschland]], [[Österreich]] und der [[Schweiz]] mit den Verbindungen zwischen einigen Städten. Dieses Beispiel ist ein ungerichteter Graph mit 10 Knoten.]]&lt;br /&gt;
|[[Datei:DepthFirstSearch tree cities de.gif|mini|350x350px|Der Baum, welcher entsteht, wenn man Tiefensuche auf die Landkarte anwendet und in Hannover startet. Dieser Baum hat die Höhe 6. Daher hat die Tiefensuche in diesem Fall die maximale [[Rekursionstiefe]] 6.]]&lt;br /&gt;
|}&lt;br /&gt;
Der Index der [[Rekursionstiefe]] der [[Rekursive Programmierung|rekursiven]] [[Methode (Programmierung)|Methode]] oder [[Prozedur (Programmierung)|Prozedur]] für die Tiefensuche entspricht dem [[Weg (Graphentheorie)|Knotenabstand]] des aktuell durchlaufenen [[Knoten (Graphentheorie)|Knotens]] vom Startknoten im in der rechten Abbildung gezeigten [[Baum (Graphentheorie)|Baum]]. Dieser Index müsste, um zum Beispiel auf der Konsole ausgegeben zu werden, in einer [[Variable (Programmierung)|Variablen]] gespeichert werden. Diese rekursive Methode oder Prozedur wird so oft aufgerufen, wie die Anzahl der Knoten des [[Graph (Graphentheorie)|Graphen]] ist. Die Rekursion bricht ab, wenn der aktuell durchlaufene Knoten nur Nachbarknoten hat, die schon vorher durchlaufen wurden.&lt;br /&gt;
&lt;br /&gt;
Im Beispiel mit den Städten (siehe oben) gibt es folgende [[Rekursive Programmierung|rekursive]] Aufrufe:&lt;br /&gt;
&lt;br /&gt;
* Hannover (Startknoten, &amp;#039;&amp;#039;&amp;#039;Rekursionstiefe&amp;#039;&amp;#039;&amp;#039; 0)&lt;br /&gt;
* Frankfurt (Nachbarknoten von Hannover, &amp;#039;&amp;#039;&amp;#039;Rekursionstiefe&amp;#039;&amp;#039;&amp;#039; 1)&lt;br /&gt;
* Zürich (Nachbarknoten von Frankfurt, &amp;#039;&amp;#039;&amp;#039;Rekursionstiefe&amp;#039;&amp;#039;&amp;#039; 2)&lt;br /&gt;
* München (Nachbarknoten von Zürich, &amp;#039;&amp;#039;&amp;#039;Rekursionstiefe&amp;#039;&amp;#039;&amp;#039; 3)&lt;br /&gt;
* Stuttgart (Nachbarknoten von München, &amp;#039;&amp;#039;&amp;#039;Rekursionstiefe&amp;#039;&amp;#039;&amp;#039; 4)&lt;br /&gt;
* Hamburg (Nachbarknoten von Stuttgart, &amp;#039;&amp;#039;&amp;#039;Rekursionstiefe&amp;#039;&amp;#039;&amp;#039; 5)&lt;br /&gt;
* Mannheim (Nachbarknoten von Hamburg, &amp;#039;&amp;#039;&amp;#039;Rekursionstiefe&amp;#039;&amp;#039;&amp;#039; 6)&lt;br /&gt;
* Dresden (Nachbarknoten von Stuttgart, &amp;#039;&amp;#039;&amp;#039;Rekursionstiefe&amp;#039;&amp;#039;&amp;#039; 5)&lt;br /&gt;
* Wien (Nachbarknoten von München, &amp;#039;&amp;#039;&amp;#039;Rekursionstiefe&amp;#039;&amp;#039;&amp;#039; 4)&lt;br /&gt;
* Berlin (Nachbarknoten von Wien, &amp;#039;&amp;#039;&amp;#039;Rekursionstiefe&amp;#039;&amp;#039;&amp;#039; 5)&lt;br /&gt;
&lt;br /&gt;
Der [[Weg (Graphentheorie)|Knotenabstand]] bezieht sich immer auf den Startknoten. Im links dargestellten ungerichteten Graphen ist es Hannover. Bei [[Gerichteter Graph|gerichteten Graphen]] ist der [[Weg (Graphentheorie)|Knotenabstand]] zwischen zwei &amp;#039;&amp;#039;verschiedenen&amp;#039;&amp;#039; Knoten nicht &amp;#039;&amp;#039;unbedingt&amp;#039;&amp;#039; symmetrisch.&lt;br /&gt;
&lt;br /&gt;
Der [[Baum (Graphentheorie)|Baum]], den die Tiefensuche durchläuft, ist ein [[Spannbaum]] des Graphen und hängt vom Startknoten ab. Es ist außerdem wichtig, ob es sich um einen [[Gerichteter Graph|gerichteten Graphen]] oder [[Ungerichteter Graph|ungerichteten Graphen]] handelt.&lt;br /&gt;
&lt;br /&gt;
Der Knotenabstand und die [[Rekursionstiefe]] ist nur für [[Zusammenhängender Graph|zusammenhängende]] [[Graph (Graphentheorie)|Graphen]] definiert und hängt vom Startknoten ab. Für nicht zusammenhängende Graphen ist der Knotenabstand und die Rekursionstiefe nur innerhalb jeder [[Zusammenhang (Graphentheorie)|Zusammenhangskomponente]] definiert.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Hinweis&amp;#039;&amp;#039;&amp;#039;: Der in der Abbildung links oben mit den Städten gezeigte [[Graph (Graphentheorie)|Graph]] ist ein &amp;#039;&amp;#039;ungerichteter&amp;#039;&amp;#039; Graph. Die Reihenfolge der durchlaufenen [[Knoten (Graphentheorie)|Knoten]] &amp;#039;&amp;#039;kann&amp;#039;&amp;#039; sich ändern, wenn stattdessen ein anderer Startknoten oder ein [[gerichteter Graph]] genommen wird, der &amp;#039;&amp;#039;nicht&amp;#039;&amp;#039; symmetrisch ist.&lt;br /&gt;
&lt;br /&gt;
== Algorithmen ==&lt;br /&gt;
# Bestimme den [[Knoten (Graphentheorie)|Knoten]], an dem die Suche beginnen soll&lt;br /&gt;
# Expandiere den Knoten und speichere der Reihenfolge nach den kleinsten/größten (optional) noch nicht erschlossenen Nachfolger in einem [[Stapelspeicher|Stack]]&lt;br /&gt;
# Rufe [[Rekursion|rekursiv]] für jeden der Knoten in dem Stack DFS auf&lt;br /&gt;
#* Falls das gesuchte Element gefunden wurde, brich die Suche ab und liefere ein Ergebnis&lt;br /&gt;
#* Falls es keine nicht erschlossenen [[Nachfolger (Mathematik)|Nachfolger]] mehr gibt, lösche den obersten Knoten aus dem Stack und rufe für den jetzt oberen Knoten im Stack DFS auf&lt;br /&gt;
&lt;br /&gt;
 &amp;#039;&amp;#039;&amp;#039;DFS&amp;#039;&amp;#039;&amp;#039;(node, goal)&lt;br /&gt;
 {&lt;br /&gt;
     if (node == goal)&lt;br /&gt;
     {&lt;br /&gt;
         return node;&lt;br /&gt;
     }&lt;br /&gt;
     else&lt;br /&gt;
     {&lt;br /&gt;
         stack := expand (node)&lt;br /&gt;
         while (&amp;#039;&amp;#039;stack is not empty&amp;#039;&amp;#039;)&lt;br /&gt;
         {&lt;br /&gt;
             node&amp;#039; := pop(stack);&lt;br /&gt;
             &amp;#039;&amp;#039;&amp;#039;DFS&amp;#039;&amp;#039;&amp;#039;(node&amp;#039;, goal);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=== Erzeugen des Tiefensuchwaldes ===&lt;br /&gt;
Der folgende rekursive [[Algorithmus]] in [[Pseudocode]] erzeugt den Tiefensuchwald eines [[Graph (Graphentheorie)|Graphen]] G mittels Setzen von Discovery- und Finishing-Times und Färben der [[Knoten (Graphentheorie)|Knoten]]. In Anlehnung an [[Thomas H. Cormen|Cormen]] et al. werden zunächst alle Knoten weiß gefärbt. Anschließend startet die Tiefensuche per Definition beim alphabetisch kleinsten Knoten und färbt diesen grau. Danach wird, wie oben beschrieben [[Rekursion|rekursiv]] dessen weißer Nachbar betrachtet und grau gefärbt. Existiert kein weißer Nachbar mehr, kommt es zum [[Backtracking]], während dessen alle durchwanderten Knoten schwarz gefärbt werden.&amp;lt;ref&amp;gt;{{Literatur |Autor=Thomas H. Cormen, [[Charles Leiserson]], [[Ronald L. Rivest]], Clifford Stein |Titel=Algorithmen – Eine Einführung |Auflage=3 |Verlag=Oldenbourg Wissenschaftsverlag |Ort=München |Datum=2010 |ISBN=978-3-486-59002-9 |Seiten=613–622}}&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;#039;&amp;#039;&amp;#039;DFS&amp;#039;&amp;#039;&amp;#039;(G)&lt;br /&gt;
     &amp;#039;&amp;#039;&amp;#039;for each&amp;#039;&amp;#039;&amp;#039; v of G // Alle Knoten weiß färben, Vorgänger auf nil setzen&lt;br /&gt;
     {&lt;br /&gt;
         col[v] = &amp;#039;w&amp;#039;;&lt;br /&gt;
         pi[v] = nil;&lt;br /&gt;
     }&lt;br /&gt;
     time = 0;&lt;br /&gt;
     &amp;#039;&amp;#039;&amp;#039;for each&amp;#039;&amp;#039;&amp;#039; u of G // Für alle weißen Knoten: DFS-visit aufrufen&lt;br /&gt;
     {&lt;br /&gt;
         if col[u] == &amp;#039;w&amp;#039;&lt;br /&gt;
         DFS-visit(u);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
 &amp;#039;&amp;#039;&amp;#039;DFS-visit&amp;#039;&amp;#039;&amp;#039;(u)&lt;br /&gt;
  1  col[u] = &amp;#039;g&amp;#039;;            // Aktuellen Knoten grau färben&lt;br /&gt;
  2  time++;                  // Zeitzähler erhöhen&lt;br /&gt;
  3  d[u] = time;             // Entdeckzeit des aktuellen Knotens setzen&lt;br /&gt;
  4  &amp;#039;&amp;#039;&amp;#039;for each&amp;#039;&amp;#039;&amp;#039; v of Adj[u]     // Für alle weißen Nachbarn des aktuellen Knotens&lt;br /&gt;
  5  {&lt;br /&gt;
  6      &amp;#039;&amp;#039;&amp;#039;if&amp;#039;&amp;#039;&amp;#039; col[v] == &amp;#039;w&amp;#039;&lt;br /&gt;
  7      {&lt;br /&gt;
  8          pi[v] = u;       // Vorgänger auf aktuellen Knoten setzen&lt;br /&gt;
  9          DFS-visit(v);    // DFS-visit aufrufen&lt;br /&gt;
 10      }&lt;br /&gt;
 11      &amp;#039;&amp;#039;&amp;#039;if&amp;#039;&amp;#039;&amp;#039; col[v] == &amp;#039;g&amp;#039;&lt;br /&gt;
 12      {&lt;br /&gt;
 13          // Zyklus entdeckt&lt;br /&gt;
 14      }&lt;br /&gt;
 15  }&lt;br /&gt;
 16  col[u] = &amp;#039;s&amp;#039;;            // Aktuellen Knoten schwarz färben&lt;br /&gt;
 17  time++;&lt;br /&gt;
 18  f[u] = time;             // Finishing-Time des aktuellen Knotens setzen&lt;br /&gt;
Den [[Zeitstempel]] (siehe Zeilen 2, 17, 18) kann man weiterhin für eine [[topologische Sortierung]] verwenden. Nachdem ein [[Knoten (Graphentheorie)|Knoten]] schwarz gefärbt wurde, wird er einer [[Liste (Datenstruktur)|Liste]], absteigend nach den Werten f[u] für die Zeitstempel, hinzugefügt und man erhält eine topologische Reihenfolge. Wird ein [[Zyklus (Graphentheorie)|Zyklus]] (siehe Zeile 9) entdeckt, ist dies nicht mehr möglich.&lt;br /&gt;
&lt;br /&gt;
== Programmierung ==&lt;br /&gt;
Das folgende Beispiel in der [[Programmiersprache]] [[C-Sharp|C#]] zeigt die Implementierung der Tiefensuche für einen [[Gerichteter Graph|gerichteten Graphen]]. Der gerichtete Graph wird als [[Klasse (Objektorientierung)|Klasse]] &amp;#039;&amp;#039;DirectedGraph&amp;#039;&amp;#039; deklariert. Die Methode &amp;#039;&amp;#039;DepthFirstSearch&amp;#039;&amp;#039;, die die Knoten durchläuft und in einer [[Liste (Datenstruktur)|Liste]] speichert, verwendet einfache [[Rekursive Programmierung|Rekursion]]. Bei der Ausführung des Programms wird die [[Methode (Programmierung)|Methode]] &amp;#039;&amp;#039;Main&amp;#039;&amp;#039; verwendet, die die Liste der markierten Knoten auf der Konsole ausgibt.&amp;lt;ref name=&amp;quot;:0&amp;quot;&amp;gt;GeeksforGeeks: [https://www.geeksforgeeks.org/depth-first-search-or-dfs-for-a-graph/ Depth First Search or DFS for a Graph]&amp;lt;/ref&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c#&amp;quot;&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Collections.Generic;&lt;br /&gt;
&lt;br /&gt;
// Deklariert die Klasse für die Knoten des Graphen&lt;br /&gt;
class Node&lt;br /&gt;
{&lt;br /&gt;
	public int index;&lt;br /&gt;
	public string value;&lt;br /&gt;
	public List&amp;lt;Node&amp;gt; adjacentNodes = new List&amp;lt;Node&amp;gt;(); // Liste der Nachbarknoten&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Deklariert die Klasse für den gerichteten Graphen&lt;br /&gt;
class DirectedGraph&lt;br /&gt;
{&lt;br /&gt;
	// Diese Methode verbindet die Knoten startNode und targetNode miteinander.&lt;br /&gt;
	public void ConnectNodes(Node startNode, Node targetNode)&lt;br /&gt;
	{&lt;br /&gt;
		startNode.adjacentNodes.Add(targetNode);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
class Program&lt;br /&gt;
{&lt;br /&gt;
	// Diese Methode gibt die Liste der Knoten in der Form A, B, C, ... als Text zurück.&lt;br /&gt;
	public static string ToString(List&amp;lt;Node&amp;gt; traversedNodes)&lt;br /&gt;
	{&lt;br /&gt;
		string text = &amp;quot;&amp;quot;;&lt;br /&gt;
		for (int i = 0; i &amp;lt; traversedNodes.Count; i++) // for-Schleife, die die Knoten durchläuft&lt;br /&gt;
		{&lt;br /&gt;
			text += traversedNodes[i].value + &amp;quot;, &amp;quot;;&lt;br /&gt;
		}&lt;br /&gt;
		text = text.Substring(0, text.Length - 2);&lt;br /&gt;
		return text;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// Diese Methode durchläuft die Knoten des gerichteten Graphen mit einer Tiefensuche&lt;br /&gt;
	public static void DepthFirstSearch(Node startNode, List&amp;lt;Node&amp;gt; traversedNodes)&lt;br /&gt;
	{&lt;br /&gt;
		traversedNodes.Add(startNode); // Fügt den aktuellen Knoten der Menge der markierten Knoten hinzu&lt;br /&gt;
		foreach (Node node in startNode.adjacentNodes) // foreach-Schleife, die alle benachbarten Knoten des Knotens durchläuft&lt;br /&gt;
		{&lt;br /&gt;
			if (!traversedNodes.Contains(node)) // Wenn der Knoten noch nicht markiert wurde&lt;br /&gt;
			{&lt;br /&gt;
				DepthFirstSearch(node, traversedNodes); // Rekursiver Aufruf der Methode mit dem Nachbarknoten als Startknoten&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// Hauptmethode, die das Programm ausführt&lt;br /&gt;
	public static void Main(String[] args)&lt;br /&gt;
	{&lt;br /&gt;
		// Deklariert und initialisiert 4 Knoten&lt;br /&gt;
		Node node1 = new Node{index = 0, value = &amp;quot;A&amp;quot;};&lt;br /&gt;
		Node node2 = new Node{index = 1, value = &amp;quot;B&amp;quot;};&lt;br /&gt;
		Node node3 = new Node{index = 2, value = &amp;quot;C&amp;quot;};&lt;br /&gt;
		Node node4 = new Node{index = 3, value = &amp;quot;D&amp;quot;};&lt;br /&gt;
		&lt;br /&gt;
		// Erzeugt einen gerichteten Graphen&lt;br /&gt;
		DirectedGraph directedGraph = new DirectedGraph();&lt;br /&gt;
		&lt;br /&gt;
		// Verbindet Knoten des Graphen miteinander&lt;br /&gt;
		directedGraph.ConnectNodes(node1, node2);&lt;br /&gt;
		directedGraph.ConnectNodes(node1, node3);&lt;br /&gt;
		directedGraph.ConnectNodes(node2, node3);&lt;br /&gt;
		directedGraph.ConnectNodes(node3, node1);&lt;br /&gt;
		directedGraph.ConnectNodes(node3, node4);&lt;br /&gt;
		directedGraph.ConnectNodes(node4, node4);&lt;br /&gt;
		&lt;br /&gt;
		List&amp;lt;Node&amp;gt; traversedNodes = new List&amp;lt;Node&amp;gt;(); // Liste der Knoten für die Tiefensuche&lt;br /&gt;
		DepthFirstSearch(node3, traversedNodes); // Aufruf der Methode&lt;br /&gt;
		Console.WriteLine(ToString(traversedNodes)); // Ausgabe auf der Konsole&lt;br /&gt;
		&lt;br /&gt;
		Console.ReadLine();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;#039;&amp;#039;&amp;#039;Hinweise&amp;#039;&amp;#039;&amp;#039;: Für die Nachbarknoten wurde eine [[Liste (Datenstruktur)|Liste]] als [[Datentyp]] verwendet, damit die Reihenfolge der durchlaufenen [[Knoten (Graphentheorie)|Knoten]] eindeutig ist und die Knoten in allen Ebenen von links nach rechts durchlaufen werden. Für den Datentyp [[Menge (Datenstruktur)|Menge]] zum Beispiel muss das nicht der Fall sein. Statt dem &amp;#039;&amp;#039;HashSet&amp;#039;&amp;#039; ([[Menge (Datenstruktur)|Menge]]) &amp;#039;&amp;#039;visitedNodes&amp;#039;&amp;#039; kann auch eine Liste oder ein Array vom Typ &amp;#039;&amp;#039;bool&amp;#039;&amp;#039; ([[Boolesche Variable]]) verwendet werden, wie im Einzelnachweis gezeigt.&amp;lt;ref name=&amp;quot;:0&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Eigenschaften ==&lt;br /&gt;
Im Folgenden werden [[Speicherbedarf]] und [[Laufzeit (Informatik)|Laufzeit]] des Algorithmus in [[Landau-Symbole|Landau-Notation]] angegeben. Wir gehen außerdem von einem [[Gerichteter Graph|gerichteten Graphen]] aus.&lt;br /&gt;
&lt;br /&gt;
=== Speicherplatz ===&lt;br /&gt;
Der [[Speicherbedarf]] des [[Algorithmus]] wird ohne den [[Speicherplatz]] für den [[Graph (Graphentheorie)|Graphen]], wie er übergeben wird, angegeben, denn dieser kann in verschiedenen Formen mit unterschiedlichem Speicherbedarf vorliegen, z.&amp;amp;nbsp;B. als [[verkettete Liste]], als [[Adjazenzmatrix]] oder als [[Inzidenzmatrix]].&lt;br /&gt;
&lt;br /&gt;
Für die oben beschriebene Prozedur &amp;#039;&amp;#039;DFS(G)&amp;#039;&amp;#039; werden zunächst alle [[Knoten (Graphentheorie)|Knoten]] weiß gefärbt und die Referenzen für deren [[Vorgänger (Mathematik)|Vorgänger]] entfernt. Diese Informationen benötigt also für jeden Knoten konstanten [[Speicherplatz]], also &amp;lt;math&amp;gt;\mathcal{O}(1)&amp;lt;/math&amp;gt;. Insgesamt ergibt sich ein linearer Speicherbedarf von &amp;lt;math&amp;gt;\mathcal{O}(\vert V \vert)&amp;lt;/math&amp;gt;, abhängig von der Anzahl der Knoten &amp;lt;math&amp;gt;\vert V \vert&amp;lt;/math&amp;gt; (englisch &amp;#039;&amp;#039;vertices&amp;#039;&amp;#039;). Der Speicherbedarf der [[Variable (Programmierung)|Variable]] &amp;#039;&amp;#039;time&amp;#039;&amp;#039; ist mit konstantem &amp;lt;math&amp;gt;\mathcal{O}(1)&amp;lt;/math&amp;gt; gegenüber &amp;lt;math&amp;gt;\mathcal{O}(\vert V \vert)&amp;lt;/math&amp;gt; vernachlässigbar. Anschließend wird für jeden Knoten &amp;#039;&amp;#039;u&amp;#039;&amp;#039; die Prozedur &amp;#039;&amp;#039;DFS-visit(u)&amp;#039;&amp;#039; aufgerufen. Da es sich hierbei nur um Kontrollstrukturen handelt, tragen sie nicht zum Speicherbedarf bei.&lt;br /&gt;
&lt;br /&gt;
Die Prozedur DFS-visit(u) arbeitet auf der bereits aufgebauten Speicherstruktur, in der alle [[Knoten (Graphentheorie)|Knoten]] abgelegt sind, und erweitert diese pro Knoten noch um die Entdeckzeit und die Finishing-Time, jeweils konstant &amp;lt;math&amp;gt;\mathcal{O}(1)&amp;lt;/math&amp;gt;. Das ändert nichts am bisherigen linearen Speicherbedarf &amp;lt;math&amp;gt;\mathcal{O}(\vert V \vert)&amp;lt;/math&amp;gt;. Da sonst in DFS-visit(u) keine weiteren Variablen mehr eingeführt werden, hat die Tiefensuche einen Speicherbedarf von &amp;lt;math&amp;gt;\mathcal{O}(\vert V \vert)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Laufzeit ===&lt;br /&gt;
Falls der Graph als [[Adjazenzliste]] gespeichert wurde, müssen im [[Worst Case]] alle möglichen [[Pfad (Graphentheorie)|Pfade]] zu allen möglichen [[Knoten (Graphentheorie)|Knoten]] betrachtet werden. Damit beträgt die [[Zeitkomplexität|Laufzeit]] von Tiefensuche &amp;lt;math&amp;gt;\mathcal{O}(\vert V \vert + \vert E \vert)&amp;lt;/math&amp;gt;, wobei &amp;lt;math&amp;gt; \vert V \vert &amp;lt;/math&amp;gt; für die Anzahl der Knoten und &amp;lt;math&amp;gt; \vert E \vert &amp;lt;/math&amp;gt; für die Anzahl der [[Kante (Graphentheorie)|Kanten]] im [[Graph (Graphentheorie)|Graph]] stehen.&amp;lt;ref&amp;gt;{{Literatur |Autor=Thomas Ottmann, Peter Widmayer |Titel=Algorithmen und Datenstrukturen |Auflage=5 |Verlag=Spektrum Akademischer Verlag |Ort=Heidelberg |Datum=2012 |ISBN=978-3-8274-2803-5 |Seiten=589-668}}&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Vollständigkeit ===&lt;br /&gt;
Falls ein [[Graph (Graphentheorie)|Graph]] unendlich groß ist oder kein Test auf [[Zyklus (Graphentheorie)|Zyklen]] durchgeführt wird, so ist die Tiefensuche nicht vollständig. Es kann also sein, dass ein Ergebnis – obwohl es existiert – nicht gefunden wird.&lt;br /&gt;
&lt;br /&gt;
=== Optimalität ===&lt;br /&gt;
Tiefensuche ist insbesondere bei [[Monoton steigende Funktion|monoton steigenden]] Pfadkosten nicht optimal, da eventuell ein Ergebnis gefunden wird, zu welchem ein sehr viel längerer [[Pfad (Graphentheorie)|Pfad]] führt als zu einem alternativen Ergebnis. Dafür wird ein solches Ergebnis im&amp;amp;nbsp;Allgemeinen deutlich schneller gefunden als bei der in diesem Fall optimalen, aber sehr viel speicheraufwendigeren [[Breitensuche]]. Als Kombination von Tiefen- und Breitensuche gibt es die [[iterative Tiefensuche]].&lt;br /&gt;
&lt;br /&gt;
== Anwendungen ==&lt;br /&gt;
[[Datei:MAZE 30x20 DFS.ogv|mini|[[Algorithmus]], der Tiefensuche verwendet, um einen [[Irrgarten]] zu erzeugen.]]&lt;br /&gt;
Die Tiefensuche ist indirekt an vielen komplexeren [[Algorithmus|Algorithmen]] für [[Graph (Graphentheorie)|Graphen]] beteiligt. Beispiele:&lt;br /&gt;
&lt;br /&gt;
* Das Auffinden aller [[Starke Zusammenhangskomponente|starken Zusammenhangskomponenten]] eines Graphen.&lt;br /&gt;
* Das Ermitteln von 2-[[Zusammenhängender Graph|zusammenhängenden]] Komponenten.&lt;br /&gt;
* Das Ermitteln von 3-zusammenhängenden Komponenten.&lt;br /&gt;
* Das Ermitteln der [[Brücke (Graphentheorie)|Brücken]] eines Graphen.&lt;br /&gt;
* Einen Graphen testen, ob er ein [[planarer Graph]] ist.&amp;lt;ref&amp;gt;{{cite journal&lt;br /&gt;
 | last1 = Hopcroft | first1 = John&lt;br /&gt;
 | last2 = Tarjan | first2 = Robert E.&lt;br /&gt;
 | doi = 10.1145/321850.321852&lt;br /&gt;
 | issue = 4&lt;br /&gt;
 | journal = [[Journal of the ACM|Journal of the Association for Computing Machinery]]&lt;br /&gt;
 | pages = 549–568&lt;br /&gt;
 | title = Efficient planarity testing&lt;br /&gt;
 | volume = 21&lt;br /&gt;
 | year = 1974&lt;br /&gt;
 }}&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;{{cite journal&lt;br /&gt;
 | last1 = de Fraysseix | first1 = H.&lt;br /&gt;
 | last2 = Ossona de Mendez | first2 = P.&lt;br /&gt;
 | last3 = Rosenstiehl | first3 = P.&lt;br /&gt;
 | journal = International Journal of Foundations of Computer Science&lt;br /&gt;
 | pages = 1017–1030&lt;br /&gt;
 | title = Trémaux Trees and Planarity&lt;br /&gt;
 | volume = 17&lt;br /&gt;
 | year = 2006&lt;br /&gt;
 | doi = 10.1142/S0129054106004248&lt;br /&gt;
 | issue = 5| arxiv=math/0610935}}&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Bei einem [[Baum (Graphentheorie)|Baum]], der Abhängigkeiten darstellt, ergeben die sortierten finish-Zeiten (siehe [[Pseudocode]] oben) eine invers-[[topologische Sortierung]].&lt;br /&gt;
* Mit der Tiefensuche kann man Graphen in [[Laufzeit (Informatik)|Laufzeit]] &amp;lt;math&amp;gt;\mathcal{O}(\vert V \vert + \vert E \vert)&amp;lt;/math&amp;gt; auf [[Kreis (Graphentheorie)|Kreise]] testen und im Falle von Kreisen die dazugehörige Kantenfolge ausgeben.&amp;lt;ref name=&amp;quot;Krumke2012&amp;quot;&amp;gt;{{Literatur |Autor=Sven Oliver Krumke, Hartmut Noltemeier |Titel=Graphentheoretische Konzepte und Algorithmen |Auflage=3 |Verlag=Springer Vieweg |Ort=Wiesbaden |Datum=2012 |ISBN=978-3-8348-1849-2 |Seiten=152-157}}&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Ein kreisfreier Graph kann mit der Tiefensuche in [[Laufzeit (Informatik)|Laufzeit]] &amp;lt;math&amp;gt;\mathcal{O}(\vert V \vert + \vert E \vert)&amp;lt;/math&amp;gt; [[Topologische Sortierung|topologisch sortiert]] werden.&amp;lt;ref name=&amp;quot;Krumke2012&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Das Lösen von Rätseln mit nur einer Lösung, z. B. [[Irrgarten|Irrgärten]]. Die Tiefensuche kann angepasst werden, um alle Lösungen für einen Irrgarten zu finden, indem nur [[Knoten (Graphentheorie)|Knoten]] auf dem aktuellen [[Pfad (Graphentheorie)|Pfad]] in die besuchte Menge aufgenommen werden.&lt;br /&gt;
* Für das Erzeugen eines [[Irrgarten]]s kann eine zufällige Tiefensuche verwendet werden.&lt;br /&gt;
&lt;br /&gt;
== Literatur ==&lt;br /&gt;
* [[Stuart Russell]], [[Peter Norvig]]: [http://aima.cs.berkeley.edu/ &amp;#039;&amp;#039;Artificial Intelligence: A Modern Approach&amp;#039;&amp;#039;.] 2. Auflage. Prentice Hall, 2002.&lt;br /&gt;
* Sven Oliver Krumke, Hartmut Noltemeier: &amp;#039;&amp;#039;Graphentheoretische Konzepte und Algorithmen&amp;#039;&amp;#039;.  3. Auflage. Springer Vieweg, 2012, ISBN 978-3-8348-1849-2&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
{{Commonscat|Depth-first search|Tiefensuche}}&lt;br /&gt;
{{Wikibooks|Algorithmensammlung: Graphentheorie: Tiefensuche|Tiefensuche|suffix=Implementierungen in der Algorithmensammlung}}&lt;br /&gt;
* [https://www-i1.informatik.rwth-aachen.de/~algorithmus/algo5.php Anschauliche Erklärung der Tiefensuche am Beispiel eines Labyrinths]&lt;br /&gt;
&lt;br /&gt;
== Einzelnachweise ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Graphsuchalgorithmus]]&lt;br /&gt;
[[Kategorie:Wikipedia:Artikel mit Video]]&lt;/div&gt;</summary>
		<author><name>imported&gt;YMS</name></author>
	</entry>
</feed>