Обхід означає відвідування всіх вузлів графа. «Обхід у глибину» або «Пошук у глибину» - це рекурсивний алгоритм пошуку всіх вершин графа або деревоподібної структури даних. У цій статті, за допомогою наведених нижче прикладів, ви дізнаєтеся: алгоритм DFS, псевдокод DFS і код алгоритму пошуку в глибину з реалізацією в програмах на C++, C, Java і Python.
Алгоритм DFS
Стандартна реалізація DFS містить кожну вершину графа в одну з двох категорій:
- Відвідані.
- Чи не відвідані.
Мета алгоритму - позначити кожну вершину, як відвідану, уникаючи циклів.
Алгоритм DFS працює таким чином:
- Почніть із розміщення будь-якої вершини графа на вершині стека.
- Візьміть верхній елемент стека та додайте його до списку відвідуваних.
- Створіть перелік суміжних вузлів цієї вершини. Додайте ті, яких немає у списку відвіданих, на початок стеку.
- Продовжуйте повторювати кроки 2 і 3, доки стек не стане порожнім.
Приклад DFS
Давайте подивимося, як алгоритм пошуку в глибину працює на прикладі. Ми використовуємо неорієнтований граф із 5 вершинами.
Ми починаємо з вершини 0, алгоритм DFS починається з розміщення його до списку відвіданих та розміщення всіх суміжних вершин у стеку.
Потім ми відвідуємо елемент у верхній частині стека, тобто 1, і переходимо до суміжних вузлів. Так як 0 ми вже відвідали, натомість відвідуємо 2.
У вершини 2 є не відвідана суміжна вершина 4 тому ми додаємо її у верхню частину стека і відвідуємо.
Після того, як ми відвідаємо останній елемент 3, він не має відвіданих суміжних вузлів. На цьому ми завершимо перший обхід у глибину графа.
Псевдокод DFS (рекурсивна реалізація)
Псевдокод для DFS наведено нижче. Зауважте, що в функції init() ми запускаємо функцію DFS на кожному вузлі. Це пов'язано з тим, що граф може мати дві різні непов'язані частини, тому щоб переконатися, що ми покриваємо кожну вершину, ми також можемо запустити алгоритм DFS на кожному вузлі.
DFS(G, u) u.visited = true for each v ∈ G.Adj[u] if v.visited == false DFS(G,v) init() { For each u ∈ G u.visited = false For each u ∈ G DFS(G, u) }
Код DFS
Код для алгоритму пошуку в глибину з прикладом показаний нижче. Код спрощено, тому ми можемо зосередитися на алгоритмі, а не на інших деталях.
DFS в C
#include <stdio.h> #include <stdlib.h> struct node { int vertex; struct node* next; }; struct node* createNode(int v); struct Graph { int numVertices; int* visited; struct node** adjLists; // we need int** to store a two dimensional array. Similary, we need struct node** to store an array of Linked lists }; struct Graph* createGraph(int); void addEdge(struct Graph*, int, int); void printGraph(struct Graph*); void DFS(struct Graph*, int); int main() { struct Graph* graph = createGraph(4); addEdge(graph, 0, 1); addEdge(graph, 0, 2); addEdge(graph, 1, 2); addEdge(graph, 2, 3); printGraph(graph); DFS(graph, 2); return 0; } void DFS(struct Graph* graph, int vertex) { struct node* adjList = graph->adjLists[vertex]; struct node* temp = adjList; graph->visited[vertex] = 1; printf("Visited %d \n", vertex); while(temp!=NULL) { int connectedVertex = temp->vertex; if(graph->visited[connectedVertex] == 0) { DFS(graph, connectedVertex); } temp = temp->next; } } struct node* createNode(int v) { struct node* newNode = malloc(sizeof(struct node)); newNode->vertex = v; newNode->next = NULL; return newNode; } struct Graph* createGraph(int vertices) { struct Graph* graph = malloc(sizeof(struct Graph)); graph->numVertices = vertices; graph->adjLists = malloc(vertices * sizeof(struct node*)); graph->visited = malloc(vertices * sizeof(int)); int i; for (i = 0; i < vertices; i++) { graph->adjLists[i] = NULL; graph->visited[i] = 0; } return graph; } void addEdge(struct Graph* graph, int src, int dest) { // Add edge from src to dest struct node* newNode = createNode(dest); newNode->next = graph->adjLists[src]; graph->adjLists[src] = newNode; // Add edge from dest to src newNode = createNode(src); newNode->next = graph->adjLists[dest]; graph->adjLists[dest] = newNode; } void printGraph(struct Graph* graph) { int v; for (v = 0; v < graph->numVertices; v++) { struct node* temp = graph->adjLists[v]; printf("\n Adjacency list of vertex %d\n ", v); while (temp) { printf("%d -> ", temp->vertex); temp = temp->next; } printf("\n"); } }
Пошук спочатку в глибину (DFS) в C++
#include <iostream> #include <list> using namespace std; class Graph { int numVertices; list *adjLists; bool *visited; public: Graph(int V); void addEdge(int src, int dest); void DFS(int vertex); }; Graph::Graph(int vertices) { numVertices = vertices; adjLists = new list[vertices]; visited = new bool[vertices]; } void Graph::addEdge(int src, int dest) { adjLists[src].push_front(dest); } void Graph::DFS(int vertex) { visited[vertex] = true; list adjList = adjLists[vertex]; cout << vertex << " "; list::iterator i; for(i = adjList.begin(); i != adjList.end(); ++i) if(!visited[*i]) DFS(*i); } int main() { Graph g(4); g.addEdge(0, 1); g.addEdge(0, 2); g.addEdge(1, 2); g.addEdge(2, 3); g.DFS(2); return 0; }
DFS Java код (Java code)
import java.io.*; import java.util.*; class Graph { private int numVertices; private LinkedList<Integer> adjLists[]; private boolean visited[]; Graph(int vertices) { numVertices = vertices; adjLists = new LinkedList[vertices]; visited = new boolean[vertices]; for (int i = 0; i < vertices; i++) adjLists[i] = new LinkedList<Integer>(); } void addEdge(int src, int dest) { adjLists[src].add(dest); } void DFS(int vertex) { visited[vertex] = true; System.out.print(vertex + " "); Iterator ite = adjLists[vertex].listIterator(); while (ite.hasNext()) { int adj = ite.next(); if (!visited[adj]) DFS(adj); } } public static void main(String args[]) { Graph g = new Graph(4); g.addEdge(0, 1); g.addEdge(0, 2); g.addEdge(1, 2); g.addEdge(2, 3); System.out.println("Following is Depth First Traversal"); g.DFS(2); } }
DFS у Python
def dfs(graph, start, visited=None): if visited is None: visited = set() visited.add(start) print(start) for next in graph[start] - visited: dfs(graph, next, visited) return visited graph = {'0': set(['1', '2']), '1': set(['0', '3', '4']), '2': set(['0']), '3': set(['1']), '4': set(['2', '3'])} dfs(graph, '0')