티스토리 뷰

개발/Algorithm

[Algorithm] DFS & BFS

ch4njun 2021. 5. 13. 21:59
반응형
이번 포스팅에서는 코딩테스트에 자주 출제되는 그래프, 트리를 탐색하는 방법인 DFS(Depth-First Search)와 BFS(Breadth-First Search)에 대해서 소개하려고 한다.

DFS (Depth-First Search)


DFS는 하나의 노드에서 갈 수 있는 노드가 여러개 있다고 했을 때, 하나의 노드에 대해서 완벽하게 탐색하고난 후 다음 노드에 대해서 탐색하는 방법을 말한다. 좀 더 교과서적으로 정리해보자면 다음 분기(Branch)로 넘어가기 전에 해당 분기를 완벽하게 탐색하는 방법을 DFS라고 한다.

 

하나의 길로 쭈우우욱 가보고 막히면 돌아와서 다음 길로 가는 형태를 말한다.

 

보통 모든 노드를 방문해야 할 경우 DFS를 선택한다. DFS 알고리즘을 프로그래밍할 때는 일반적으로 재귀함수를 사용해 구현한다. Stack으로도 구현이 가능하지만 해당 포스트에서는 다루지 않는다.

 

DFS의 기본적인 의사코드를 살펴보자.

def dfs(current): # 현재상태를 표현하고 싶다면 인자를 통해서 배열이든 뭐든 전달하면 된다. (백트래킹 처럼!)
	visit[current] = True
    # 하고싶은걸 여기에 구현 (ex: 출력, 상태변화)
   	
    for i in range(1, N + 1):
    	# 1. 아직 방문하지 않았고, (여러 번 방문할 수 있다면 패스)
        # 2. 방문할 수 있다면, (2차원 배열로 그래프를 표현한 경우. Set으로도 표현할 수 있다)
    	if not visit[i] and matrix[current][i]:
        	dfs(i)

 

DFS의 장점은 직관적인 구현과 상태를 저장하기 쉽다는 것에 있다. 왜냐하면 재귀함수를 방문할 때마다 각자 다른 인자를 가지고 있기 때문에 인자를 통해서 상태를 표현하면 된다.

 

BFS (Breadth-First Search)


BFS는 하나의 노드에서 갈 수 있는 노드를 모두 탐색한 후 다음 깊이에 대해서 탐색하는 방법을 말한다. 즉, 시작지점에서 가까운 노드를 먼저 탐색하고 먼 노드를 나중에 탐색하는 방법이다.

 

보통 두 노드 사이의 최단 경로 및 임의의 경로를 찾고 싶을 때 이 방법을 선택한다. BFS 알고리즘을 프로그래밍할 때는 일반적으로 큐(Queue)를 사용해 구현한다.

 

BFS의 기본적인 의사코드를 살펴보자.

def bfs():
	from collections import deque
    Q = deque([])  # 최초 시작 위치를 deque에 저장한다.
    
    dirs = [(-1, 0), (1, 0), (0, -1), (0, 1)]
    while Q:
    	x, y = Q.popleft()
        
        # 노드에서 다음으로 갈 수 있는 반복
        for dir in dirs:
        	# 이동
            nx = x + dir[0]
            ny = y + dir[1]
            
            # 이동 범위에 대한 조건
            if not (0 <= nx < N and 0 <= ny < M):
            	continue
               
            # 이동 가능한지에 대한 조건
            if matrix[nx][ny] == -1:
            	continue
            # 기타 조건들을 여기에 넣으면 된다
            
            # 조건을 통해서 다음노드 추가할지 여부를 결정해도 된다
            # 상태 변경
            matrix[nx][ny] = matrix[x][y] + 1
            # Queue에 다음노드 추가
            Q.append([nx, ny])

위 예제에서 matrix를 2차원배열로 해도 되지만, 그래프를 인접 행렬로 표현해도 된다. 예를 들면 A에서 연결되는 노드가 B, C, D가 있으면 {A: [B, C, D]} 와 같이 표현해도 된다.

 

BFS에서 DFS처럼 하나의 요소마다 상태를 보관하고 싶다면 (x좌표, y좌표, 금액, 방향) 과 같이 Queue넣는 요소에 여러가지 상태를 포함시킬 수 있다. (좀 복잡해지긴한다...)

 

Python의 경우 재귀깊이에서 Recursive 에러가 발생할 수 있다. (Runtime Error)
그냥 기본적으로 재귀깊이를 늘려주는 코드를 추가해주도록 하자.

sys.setrecursionlimit(100000)

 

 

반응형

'개발 > Algorithm' 카테고리의 다른 글

[Algorithm] 코딩테스트 Cheat Sheet  (0) 2021.04.25
[Algorithm] Dynamic Programming (동적 계획법)  (0) 2021.04.17
[Algorithm] Back Tracking  (0) 2021.04.03
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함