Derinlik Öncelikli Arama (DFS)
Son güncelleme
Derinlik öncelikli arama, bir grafı geri dönmeden önce her dal boyunca mümkün olduğunca derine giderek keşfeder. Bir kaynak düğümden başlayarak bir komşuyu, ardından o komşunun komşusunu ve bir çıkmaza (ziyaret edilmemiş komşusu olmayan bir düğüm) ulaşana kadar bu şekilde devam eder; o noktada geri döner ve bir sonraki dalı dener. Yukarıda oynata basarak bir yol boyunca aşağı inmesini, dibe ulaşmasını ve geri çıkmasını izleyin.
DFS doğal olarak bir yığınla ifade edilir: ya açık bir yığın (burada canlandırıldığı gibi) ya da özyineleme yoluyla çağrı yığını. Her düğüm ve kenarı bir kez ziyaret eder, bu nedenle V köşe ve E kenar içeren bir graf için O(V + E) zamanda çalışır.
Zaman ve alan karmaşıklığı
| Ölçüt | Karmaşıklık | Notlar |
|---|---|---|
| Zaman | O(V + E) | Her köşe ve kenar bir kez ziyaret edilir |
| Alan | O(V) | Yığın + ziyaret edilenler kümesi, en kötü durumda tüm düğümler |
| Gezinme | Önce en derin | Diğerlerinden önce bir dalı sonuna kadar izler |
| Veri yapısı | Yığın (veya özyineleme) | LIFO sırası derinlik öncelikli davranışı yönlendirir |
Adım adım
| Adım | Ne olur |
|---|---|
| 1 | Kaynak düğümü yığına ekle. |
| 2 | Bir düğüm çıkar; zaten ziyaret edildiyse atla. |
| 3 | Onu ziyaret edildi olarak işaretle ve ona ulaşan kenarı kaydet. |
| 4 | Ziyaret edilmemiş tüm komşularını yığına ekle. |
| 5 | Yığın boşalana kadar tekrarla. |
Çözümlü örnek
A → [B, C], B → [D], C → [E] grafında A'dan başlayan yinelemeli DFS; komşular listelenen sırada yığına eklenir (LIFO yığını en son ekleneni önce çıkarır):
| Adım | Yığın (üst sağda) | Ziyaret edilenler | İşlem |
|---|---|---|---|
| 1 | [A] | {} | Kaynak A'yı ekle. |
| 2 | [B, C] | {A} | A'yı çıkar, ziyaret edildi işaretle, komşuları B sonra C'yi ekle. |
| 3 | [B, E] | {A, C} | C'yi çıkar, ziyaret edildi işaretle, komşu E'yi ekle. |
| 4 | [B] | {A, C, E} | E'yi çıkar, ziyaret edildi işaretle, komşu yok. |
| 5 | [D] | {A, C, E, B} | B'yi çıkar, ziyaret edildi işaretle, komşu D'yi ekle. |
| 6 | [] | {A, C, E, B, D} | D'yi çıkar, ziyaret edildi işaretle, yığın boş: tamamlandı. |
DFS ne zaman kullanılır
| Şu durumda kullanın | Şu durumda kaçının |
|---|---|
| Döngü tespiti, topolojik sıralama veya bağlı bileşenleri bulmaya ihtiyacınız var. | Ağırlıksız bir grafta en kısa yola ihtiyacınız var: bunu DFS değil BFS yapar. |
| Graf geniş ve sığdır, bu yüzden yığın çok sayıda sınır düğümü içeren bir kuyruktan çok daha az bellek kullanır. | Graf çok derindir ve özyineleme kullanıyorsunuz: çağrı yığını taşabilir. |
| Labirent çözme veya geri izlemeli aramada olduğu gibi yolları kapsamlı şekilde keşfetmek istiyorsunuz. | Düğümleri kaynaktan uzaklık sırasına göre keşfetmeniz gerekiyor. |
| Erişilebilirliği veya iki düğüm arasında bir yol olup olmadığını kontrol ediyorsunuz. | Bulunan yolda en az sayıda kenarı garanti etmeniz gerekiyor. |
Depth-First Search kodu
Python, JavaScript, Java, C++, C dillerinde temiz ve çalıştırılabilir bir Depth-First Search uygulaması. Bir dil seçin, kodu kopyalayın veya Coddy Playground'da hazır yüklenmiş olarak açın.
Python ile Depth-First Search kodu
1def dfs(graph, node, visited):2 visited.add(node)3 order = [node]4 for neighbor in graph[node]:5 if neighbor not in visited:6 order.extend(dfs(graph, neighbor, visited))7 return order8
9
10graph = {11 "A": ["B", "C"],12 "B": ["D", "E"],13 "C": ["F"],14 "D": [],15 "E": ["F"],16 "F": [],17}18
19order = dfs(graph, "A", set())20print("DFS order:", " -> ".join(order))JavaScript ile Depth-First Search kodu
1const graph = {2 A: ["B", "C"],3 B: ["D", "E"],4 C: ["F"],5 D: [],6 E: ["F"],7 F: [],8};9
10function dfs(node, visited = new Set(), order = []) {11 if (visited.has(node)) return order;12 visited.add(node);13 order.push(node);14 for (const next of graph[node]) {15 dfs(next, visited, order);16 }17 return order;18}19
20console.log("DFS from A:", dfs("A").join(" -> "));Java ile Depth-First Search kodu
1import java.util.List;2
3public class Main {4 static List<List<Integer>> adj = List.of(5 List.of(1, 2), // neighbors of 06 List.of(0, 3, 4), // neighbors of 17 List.of(0, 5), // neighbors of 28 List.of(1),9 List.of(1, 5),10 List.of(2, 4)11 );12 static boolean[] visited = new boolean[6];13
14 static void dfs(int node) {15 visited[node] = true;16 System.out.print(" " + node);17 for (int next : adj.get(node)) {18 if (!visited[next]) dfs(next);19 }20 }21
22 public static void main(String[] args) {23 System.out.print("DFS from 0:");24 dfs(0);25 System.out.println();26 }27}C++ ile Depth-First Search kodu
1#include <iostream>2#include <vector>3
4void dfs(int node, const std::vector<std::vector<int>>& adj,5 std::vector<bool>& visited) {6 visited[node] = true;7 std::cout << node << " ";8 // Recurse into every unvisited neighbor9 for (int next : adj[node]) {10 if (!visited[next]) dfs(next, adj, visited);11 }12}13
14int main() {15 // 6-node undirected graph as an adjacency list16 std::vector<std::vector<int>> adj = {17 {1, 2}, // 018 {0, 3, 4}, // 119 {0, 5}, // 220 {1}, // 321 {1, 5}, // 422 {2, 4}, // 523 };24 std::vector<bool> visited(adj.size(), false);25 std::cout << "DFS from node 0: ";26 dfs(0, adj, visited);27 std::cout << "\n";28 return 0;29}C ile Depth-First Search kodu
1#include <stdbool.h>2#include <stdio.h>3
4#define N 65
6// 6-node undirected graph as an adjacency matrix7int adj[N][N] = {8 {0, 1, 1, 0, 0, 0},9 {1, 0, 0, 1, 1, 0},10 {1, 0, 0, 0, 0, 1},11 {0, 1, 0, 0, 0, 0},12 {0, 1, 0, 0, 0, 1},13 {0, 0, 1, 0, 1, 0},14};15bool visited[N];16
17void dfs(int node) {18 visited[node] = true;19 printf("%d ", node);20 // Recurse into every unvisited neighbor21 for (int next = 0; next < N; next++) {22 if (adj[node][next] && !visited[next]) dfs(next);23 }24}25
26int main(void) {27 printf("DFS from node 0: ");28 dfs(0);29 printf("\n");30 return 0;31}Derinlik Öncelikli Arama SSS
DFS'nin zaman karmaşıklığı nedir?
V köşe sayısı ve E kenar sayısı olmak üzere O(V + E) zamanda çalışır; çünkü her köşeyi bir kez ziyaret eder ve her kenara bir kez bakar. Yığın ve ziyaret edilenler kümesi için O(V) alan kullanır.DFS ile BFS arasındaki fark nedir?
DFS özyinelemeli mi yoksa yinelemeli mi?
BFS yerine DFS'yi ne zaman kullanmalıyım?
DFS en kısa yolu bulabilir mi?
DFS neden bir ziyaret edilenler kümesine ihtiyaç duyar?
O(V + E) seviyesinde tutar. Yaygın bir hata, çıkarırken düğümleri ziyaret edildi işaretleyip yine de yinelenenleri eklemektir; bu doğrudur ama yığında atlanması gereken eski girişler bırakabilir.