어떤 노드에서 다른 연관있는 노드로 이동하고
이동해서 도착한 노드에서 그 노드와 연관된 노드로 이동하고 ....
꼬리 물기 식으로 어떠한 관계가 있는 노드로 끝까지 물고 늘어지는 탐색 알고리즘이라고 나는 이해했다.
DFS 알고리즘이 이용하는 자료구조는 STACK
stack의 용도는 되돌아가기 위해서이다. (돌아갈까바그래~) 깊이 탐색하기 위해서 낮은애들부터 정복할 건데 다 정복하면 다시 위로 올라와서 정복하지 않은 아이들을 정복해 나가야 한다.
2번 노드에서 DFS를 시작한다고 가정한다면
(여러개가 이어져 있다면 노드 번호가 가장 낮은 것부터 탐색 한다)
1번을 stack에 Push -> 3번을 stack에 Push -> 2번은 방문했으니 3번을 pop 하고 -> 되돌아와서 다시 1번이랑 연결되어 있는 4번을 stack에 Push 하면서 정복해나간다.
방문의 여부를 표시하는 visted 배열
한 놈씩 정복 할 때, 이전에 정복했던 녀석들은 재방문 할 필요가 없다
위에서 3번 노드를 방문했을 때, 2번은 시작점이자 방문한 놈이었기 때문에 더이상 갈데가 없다! -> 되돌아가자! 가 된것이다.
따라서 각 노드들이 방문했는지 여부를 표시한 visited 배열이 필요하다
DFS 알고리즘은 두가지 방식으로 구성할 수 있다.
- Stack 자료구조를 이용한 방식
- Recursion 재귀를 이용한 방식
Recursion (재귀)를 이용한 방식
여러개의 도시가 있는 graph를 생각하고 모두 선으로 연결이 되어있다면
간단한 재귀를 이용한 DFS 코드는 아래와 같이 생각할 수 있다
graph = [
[],
[4, 3, 2],
[2, 4],
[1, 3, ],
[3, 5],
[3, 4],
]
visited = [False]*9
result = []
def dfs(node, graph, visited):
visited[node] = True
result.append(node)
for n in graph[node]:
if visited[n] == False:
dfs(n, graph, visited)
dfs(1, graph, visited)
print(result)
방문을 하자마자 visited를 True로 설정하고
인접한 녀석들을 돌면서 visited 가 False인 경우만 꼬리를 물면서 탐색하는 방식이다.
여기서의 for 반복문이 자료구조 Stack 역할을 대신해준다. 되돌아 갈 수 있게 해준다
돌면서 result를 저장하고 있고, recursion의 탈출은 연결되어있는 모든 노드들을 탐색하면 알아서 탈출하므로 탈출을 위한 조건문은 필요가 없다
시간 복잡도
O(N) : 각각의 노드를 한번씩 돌면서 재귀를 실행하고 있다.
'알고리즘 > DFS' 카테고리의 다른 글
[DFS] 백준 14888번 : 연산자 끼워넣기 - Python 파이썬 (0) | 2021.10.22 |
---|---|
[DFS] 재귀적 깊이 우선 탐색 메서드(함수)의 구성 - Python 파이썬 (0) | 2021.10.18 |
[DFS] 프로그래머스 고득점킷 네트워크 - Python 파이썬 (0) | 2021.10.11 |
[DFS] 프로그래머스 고득점킷 타켓넘버 - Python 파이썬 (0) | 2021.09.27 |
[DFS] 틀 모양의 아이스크림 찍어내기 (0) | 2021.08.19 |