mafulechka
17 червня 2019 р. 11:45

Алгоритм DFS ("Depth-first search" або "Пошук у глибину")

Обхід означає відвідування всіх вузлів графа. «Обхід у глибину» або «Пошук у глибину» - це рекурсивний алгоритм пошуку всіх вершин графа або деревоподібної структури даних. У цій статті, за допомогою наведених нижче прикладів, ви дізнаєтеся: алгоритм DFS, псевдокод DFS і код алгоритму пошуку в глибину з реалізацією в програмах на C++, C, Java і Python.


Алгоритм DFS

Стандартна реалізація DFS містить кожну вершину графа в одну з двох категорій:

  1. Відвідані.
  2. Чи не відвідані.

Мета алгоритму - позначити кожну вершину, як відвідану, уникаючи циклів.

Алгоритм DFS працює таким чином:

  1. Почніть із розміщення будь-якої вершини графа на вершині стека.
  2. Візьміть верхній елемент стека та додайте його до списку відвідуваних.
  3. Створіть перелік суміжних вузлів цієї вершини. Додайте ті, яких немає у списку відвіданих, на початок стеку.
  4. Продовжуйте повторювати кроки 2 і 3, доки стек не стане порожнім.

Приклад DFS

Давайте подивимося, як алгоритм пошуку в глибину працює на прикладі. Ми використовуємо неорієнтований граф із 5 вершинами.

Ми починаємо з вершини 0, алгоритм DFS починається з розміщення його до списку відвіданих та розміщення всіх суміжних вершин у стеку.

Потім ми відвідуємо елемент у верхній частині стека, тобто 1, і переходимо до суміжних вузлів. Так як 0 ми вже відвідали, натомість відвідуємо 2.

У вершини 2 є не відвідана суміжна вершина 4 тому ми додаємо її у верхню частину стека і відвідуємо.

Після того, як ми відвідаємо останній елемент 3, він не має відвіданих суміжних вузлів. На цьому ми завершимо перший обхід у глибину графа.

Псевдокод DFS (рекурсивна реалізація)

Псевдокод для DFS наведено нижче. Зауважте, що в функції init() ми запускаємо функцію DFS на кожному вузлі. Це пов'язано з тим, що граф може мати дві різні непов'язані частини, тому щоб переконатися, що ми покриваємо кожну вершину, ми також можемо запустити алгоритм DFS на кожному вузлі.

  1. DFS(G, u)
  2. u.visited = true
  3. for each v G.Adj[u]
  4. if v.visited == false
  5. DFS(G,v)
  6.  
  7. init() {
  8. For each u G
  9. u.visited = false
  10. For each u G
  11. DFS(G, u)
  12. }

Код DFS

Код для алгоритму пошуку в глибину з прикладом показаний нижче. Код спрощено, тому ми можемо зосередитися на алгоритмі, а не на інших деталях.

DFS в C

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. struct node
  5. {
  6. int vertex;
  7. struct node* next;
  8. };
  9.  
  10. struct node* createNode(int v);
  11.  
  12. struct Graph
  13. {
  14. int numVertices;
  15. int* visited;
  16. struct node** adjLists; // we need int** to store a two dimensional array. Similary, we need struct node** to store an array of Linked lists
  17. };
  18.  
  19. struct Graph* createGraph(int);
  20. void addEdge(struct Graph*, int, int);
  21. void printGraph(struct Graph*);
  22. void DFS(struct Graph*, int);
  23.  
  24.  
  25. int main()
  26. {
  27.  
  28. struct Graph* graph = createGraph(4);
  29. addEdge(graph, 0, 1);
  30. addEdge(graph, 0, 2);
  31. addEdge(graph, 1, 2);
  32. addEdge(graph, 2, 3);
  33.  
  34. printGraph(graph);
  35.  
  36. DFS(graph, 2);
  37.  
  38. return 0;
  39. }
  40.  
  41. void DFS(struct Graph* graph, int vertex) {
  42. struct node* adjList = graph->adjLists[vertex];
  43. struct node* temp = adjList;
  44.  
  45. graph->visited[vertex] = 1;
  46. printf("Visited %d \n", vertex);
  47.  
  48. while(temp!=NULL) {
  49. int connectedVertex = temp->vertex;
  50.  
  51. if(graph->visited[connectedVertex] == 0) {
  52. DFS(graph, connectedVertex);
  53. }
  54. temp = temp->next;
  55. }
  56. }
  57.  
  58.  
  59. struct node* createNode(int v)
  60. {
  61. struct node* newNode = malloc(sizeof(struct node));
  62. newNode->vertex = v;
  63. newNode->next = NULL;
  64. return newNode;
  65. }
  66.  
  67. struct Graph* createGraph(int vertices)
  68. {
  69. struct Graph* graph = malloc(sizeof(struct Graph));
  70. graph->numVertices = vertices;
  71.  
  72. graph->adjLists = malloc(vertices * sizeof(struct node*));
  73.  
  74. graph->visited = malloc(vertices * sizeof(int));
  75.  
  76. int i;
  77. for (i = 0; i < vertices; i++) {
  78. graph->adjLists[i] = NULL;
  79. graph->visited[i] = 0;
  80. }
  81. return graph;
  82. }
  83.  
  84. void addEdge(struct Graph* graph, int src, int dest)
  85. {
  86. // Add edge from src to dest
  87. struct node* newNode = createNode(dest);
  88. newNode->next = graph->adjLists[src];
  89. graph->adjLists[src] = newNode;
  90.  
  91. // Add edge from dest to src
  92. newNode = createNode(src);
  93. newNode->next = graph->adjLists[dest];
  94. graph->adjLists[dest] = newNode;
  95. }
  96.  
  97. void printGraph(struct Graph* graph)
  98. {
  99. int v;
  100. for (v = 0; v < graph->numVertices; v++)
  101. {
  102. struct node* temp = graph->adjLists[v];
  103. printf("\n Adjacency list of vertex %d\n ", v);
  104. while (temp)
  105. {
  106. printf("%d -> ", temp->vertex);
  107. temp = temp->next;
  108. }
  109. printf("\n");
  110. }
  111. }

Пошук спочатку в глибину (DFS) в C++

  1. #include <iostream>
  2. #include <list>
  3. using namespace std;
  4.  
  5. class Graph
  6. {
  7. int numVertices;
  8. list *adjLists;
  9. bool *visited;
  10.  
  11. public:
  12. Graph(int V);
  13. void addEdge(int src, int dest);
  14. void DFS(int vertex);
  15. };
  16.  
  17. Graph::Graph(int vertices)
  18. {
  19. numVertices = vertices;
  20. adjLists = new list[vertices];
  21. visited = new bool[vertices];
  22. }
  23.  
  24. void Graph::addEdge(int src, int dest)
  25. {
  26. adjLists[src].push_front(dest);
  27. }
  28.  
  29. void Graph::DFS(int vertex)
  30. {
  31.  
  32. visited[vertex] = true;
  33. list adjList = adjLists[vertex];
  34.  
  35. cout << vertex << " ";
  36.  
  37. list::iterator i;
  38. for(i = adjList.begin(); i != adjList.end(); ++i)
  39. if(!visited[*i])
  40. DFS(*i);
  41. }
  42.  
  43. int main()
  44. {
  45. Graph g(4);
  46. g.addEdge(0, 1);
  47. g.addEdge(0, 2);
  48. g.addEdge(1, 2);
  49. g.addEdge(2, 3);
  50.  
  51. g.DFS(2);
  52.  
  53. return 0;
  54. }

DFS Java код (Java code)

  1. import java.io.*;
  2. import java.util.*;
  3.  
  4.  
  5. class Graph
  6. {
  7. private int numVertices;
  8. private LinkedList<Integer> adjLists[];
  9. private boolean visited[];
  10.  
  11. Graph(int vertices)
  12. {
  13. numVertices = vertices;
  14. adjLists = new LinkedList[vertices];
  15. visited = new boolean[vertices];
  16.  
  17. for (int i = 0; i < vertices; i++)
  18. adjLists[i] = new LinkedList<Integer>();
  19. }
  20.  
  21. void addEdge(int src, int dest)
  22. {
  23. adjLists[src].add(dest);
  24. }
  25.  
  26. void DFS(int vertex)
  27. {
  28. visited[vertex] = true;
  29. System.out.print(vertex + " ");
  30.  
  31. Iterator ite = adjLists[vertex].listIterator();
  32. while (ite.hasNext())
  33. {
  34. int adj = ite.next();
  35. if (!visited[adj])
  36. DFS(adj);
  37. }
  38. }
  39.  
  40.  
  41. public static void main(String args[])
  42. {
  43. Graph g = new Graph(4);
  44.  
  45. g.addEdge(0, 1);
  46. g.addEdge(0, 2);
  47. g.addEdge(1, 2);
  48. g.addEdge(2, 3);
  49.  
  50. System.out.println("Following is Depth First Traversal");
  51.  
  52. g.DFS(2);
  53. }
  54. }

DFS у Python

  1. def dfs(graph, start, visited=None):
  2. if visited is None:
  3. visited = set()
  4. visited.add(start)
  5. print(start)
  6. for next in graph[start] - visited:
  7. dfs(graph, next, visited)
  8. return visited
  9.  
  10. graph = {'0': set(['1', '2']),
  11. '1': set(['0', '3', '4']),
  12. '2': set(['0']),
  13. '3': set(['1']),
  14. '4': set(['2', '3'])}
  15.  
  16. dfs(graph, '0')

Вам це подобається? Поділіться в соціальних мережах!

Коментарі

Only authorized users can post comments.
Please, Log in or Sign up