여름의 서재
[알고리즘 종류] DFS(깊이우선탐색) & BFS(너비우선탐색) 본문
728x90
- DFS (Depth-first Search)
: 루트 노드에서 시작해서 다음 분기(branch)로 넘어가기 전에 해당 분기를 완벽하게 탐색하는 방식
ex) 미로찾기를 할 때 최대한 한 방향으로 갈 수 있을 때까지 쭉 가다가 더 이상 갈 수 없게 되면 다시 가장 가까운 갈림길로 돌아와서 그 갈림길부터 다시 다른 방향으로 탐색을 진행하는 것이 깊이 우선 탐색 방식.
1. 모든 노드를 방문하고자 하는 경우에 이 방법을 선택함
2. 깊이 우선 탐색(DFS)이 너비 우선 탐색(BFS)보다 좀 더 간단함
3. 검색 속도 자체는 너비 우선 탐색(BFS)에 비해서 느림
- stack을 통해서 구현 가능
def DFS(graph, root):
visited = []
stack = [root]
while stack:
n = stack.pop()
if n not in visited:
visited.append(n)
stack += graph[n] - set(visited) # 연결된 노드 중 방문한 노드를 빼고 stack에 추가
return visited
# 애초에 그래프 또한 graph = {1:set(2,3),2:..} 이런 형태여야 함
- BFS (Breadth-first Search)
: 시작점인 루트 노드와 같은 거리에 있는 노드를 우선으로 탐색하는 방식
주로 두 노드 사이의 최단 경로를 찾고 싶을 때 이 방법을 선택.
ex) 지구 상에 존재하는 모든 친구 관계를 그래프로 표현한 후 Sam과 Eddie사이에 존재하는 경로를 찾는 경우
* 깊이 우선 탐색의 경우 - 모든 친구 관계를 다 살펴봐야 할지도 모름
* 너비 우선 탐색의 경우 - Sam과 가까운 관계부터 탐색
- deque를 이용해 구현 가능
from collections import deque
def BFS(graph, root):
visited = []
queue = deque([root])
while queue:
n = queue.popleft()
if n not in visited:
visited.append(n)
queue += graph[n] - set(visited)
return visited
📄 활용 문제
백준 1260_ DFS와 BFS
문제
그래프를 DFS로 탐색한 결과와 BFS로 탐색한 결과를 출력하는 프로그램을 작성하시오. 단, 방문할 수 있는 정점이 여러 개인 경우에는 #¹정점 번호가 작은 것을 먼저 방문하고, 더 이상 방문할 수 있는 점이 없는 경우 종료한다. 정점 번호는 1번부터 N번까지이다.
입력
첫째 줄에 정점의 개수 N(1 ≤ N ≤ 1,000), 간선의 개수 M(1 ≤ M ≤ 10,000), 탐색을 시작할 정점의 번호 V가 주어진다. 다음 M개의 줄에는 간선이 연결하는 두 정점의 번호가 주어진다. 어떤 두 정점 사이에 여러 개의 간선이 있을 수 있다. 입력으로 주어지는 간선은 #²양방향이다.
출력
첫째 줄에 DFS를 수행한 결과를, 그 다음 줄에는 BFS를 수행한 결과를 출력한다. V부터 방문된 점을 순서대로 출력하면 된다.
from collections import deque
def DFS(graph, root):
visited = []
stack = [root]
while stack:
n = stack.pop()
if n not in visited:
visited.append(n)
if n in graph:
temp = list(set(graph[n]) - set(visited))
temp.sort(reverse=True) # 1 작은 것부터 방문하기 위해
stack += temp
return visited
def BFS(graph, root):
visited = []
queue = deque([root])
while queue:
n = queue.popleft()
if n not in visited:
visited.append(n)
if n in graph:
temp = list(set(graph[n]) - set(visited))
temp.sort() # 1 작은 것부터 방문하기 위해
queue += temp
return visited
graph = {}
node, edge, start = map(int, input().split())
for i in range(edge):
n1, n2 = map(int, input().split())
# 2 양방향이기 때문에
if n1 not in graph:
graph[n1] = [n2]
elif n2 not in graph[n1]:
graph[n1].append(n2)
if n2 not in graph:
graph[n2] = [n1]
elif n1 not in graph[n2]:
graph[n2].append(n1)
print(*DFS(graph, start))
print(*BFS(graph, start))
'알고리즘 > 알고리즘 종류' 카테고리의 다른 글
[알고리즘 종류] 동적 계획법(Dynamic Programming) (0) | 2021.08.18 |
---|---|
[알고리즘 종류] 투 포인터(Two Pointer) (0) | 2021.08.16 |
[알고리즘 종류] 보이어-무어 알고리즘 (0) | 2021.08.13 |
[알고리즘 종류] KMP 알고리즘 (0) | 2021.08.13 |
[알고리즘 종류] 브루트 포스 (Brute Force) (0) | 2021.08.13 |
Comments