현의 개발 블로그

DFS, BFS 본문

프로그래밍 언어/파이썬

DFS, BFS

hyun2371 2023. 5. 8. 15:44

DFS

DFS(Depth First Search)는 깊이 우선 탐색이다. 그래프에서 깊은 부분을 우선적으로 탐색한다.

 

1) 탐색 시작 노드를 스택에 삽입하고 방문 처리를 한다.

 

2) 스택 최상단 노드에 방문하지 않은 인접노드가 있으면 스택에 넣고 방문 처리를 한다.

   인접 노드가 여러 개인 경우 숫자가 작은 노드를 꺼낸다.

   방문하지 않은 인접 노드가 없으면 해당 노드를 스택에서 꺼낸다.

 

3) 2번 과정을 수행할 수 없을 때까지 반복한다.

 

예제

시작 노드인 ‘1’을 스택에 삽입하고 방문 처리를 한다.

스택 1

 

최상단 노드 ‘1’에 인접한 노드 중 방문하지 않은 노드는 ‘2’, ‘4’이다

그중 작은 노드인 ‘2’를 스택에 넣고 방문 처리를 한다.

스택 1 2

 

최상단 노드 ‘2’에 인접한 노드 중 방문하지 않은 노드는 ‘5’, ‘6’이다

그중 작은 노드 ‘5’를 스택에 넣고 방문 처리를 한다.

스택 1 2 5

 

최상단 노드 ‘5’에 인접한 노드 중 방문하지 않은 노드는 ‘4’, ‘7’이다.

그중 작은 노드 ‘4’를 스택에 넣고 방문 처리를 한다.

스택 1 2 5 4

 

최상단 노드 ‘4’에 인접한 노드 중 방문하지 않은 노드는 ‘3’이다

‘3’을 스택에 넣고 방문 처리를 한다.

스택 1 2 5 4 3

 

최상단 노드 ‘3’에 인접한 노드 중 방문하지 않은 노드는 없다.

‘3’을 스택에서 꺼낸다.

스택 1 2 5 4

 

최상단 노드 ‘4’에 인접한 노드 중 방문하지 않은 노드는 없다.

‘4’를 스택에서 꺼낸다.

스택 1 2 5

 

최상단 노드 ‘5’에 인접한 노드 중 방문하지 않은 노드는 ‘7’이다.

‘7’을 스택에 넣고 방문 처리를 한다.

스택 1 2 5 7

 

최상단 노드 ‘7’에 인접한 노드 중 방문하지 않은 노드는 ‘6’이다.

‘6’을 스택에 넣고 방문 처리를 한다.

스택 1 2 5 7 6

 

 

남아 있는 노드에 방문하지 않은 인접 노드가 없다.

결과적으로 노드의 탐색 순서는 1→2→5→4→3→7→6 이다.

구현 코드

def dfs(graph, v, visited):
    # 현재 노드 방문 처리
    visited[v] = True
    print(v, end=' ')

    # 현재 노드와 연결된 다른 노드 재귀적으로 방문
    for i in graph[v]:
        if not visited[i]:
            dfs(graph, i, visited)

# 각 노드 연결 정보
graph = [
    [],
    [2,4],
    [1, 5, 6],
    [4],
    [1, 3, 5],
    [2, 4, 7],
    [2, 7],
    [5, 6],
]

# 각 노드 방문 정보
visited = [False] * 8

dfs(graph, 1, visited)

 

 

BFS

BFS(Breadth First Search)는 너비 우선 탐색이다.

가까운 노드부터 탐색하는 알고리즘이다.

 

1) 탐색 시작 노드를 큐에 삽입하고 방문 처리를 한다.

2) 큐에서 노드를 꺼낸다. 해당 노드의 인접 노드 중 방문하지 않은 노드들을 스택에 삽입하고 방문 처리를 한다.

3) 2번 과정을 수행할 수 없을 때까지 반복한다.

예제

시작 노드인 1을 큐에 삽입하고 방문 처리를 한다.

큐 1

 

큐에서 1을 꺼낸다. 1에 인접한 노드 ‘2’, ‘4’를 큐에 삽입하고 방문 처리를 한다.

큐 2 4

 

큐에서 노드 ‘2’를 꺼낸다.

방문하지 않은 인접노드 ‘5’, ‘6’을 큐에 삽입하고 방문 처리를 한다.

큐 4 5 6

 

큐에서 노드 ‘4’를 꺼낸다

‘4’ 인접 노드 중 방문하지 않은 ‘3’을 큐에 삽입하고 방문 처리를 한다.

큐 5 6 3

 

큐에서 노드 ‘5’를 꺼낸다.

‘5’ 인접 노드 중 방문하지 않은 ‘7’을 큐에 삽입하고 방문 처리를 한다

큐 6 3 7

 

큐에서 ‘6’을 꺼낸다

‘6’ 인접 노드 중 방문하지 않은 노드가 없으므로 무시한다.

 

남아 있는 노드들에도 방문하지 않은 인접 노드가 없으므로 큐에서 차례로 꺼낸다.

 

탐색 순서: 1→ 2 → 4 → 5→ 6→ 3→ 7

구현 코드

편의를 위해 graph[0]은 비워두고 1~7까지 사용하였다.

from collections import deque

def bfs(graph, start, visited):
    queue = deque([start])
    visited[start] = True
    # 큐가 빌 때까지 반복
    while queue:
        v = queue.popleft()
        print(v, end=' ')

        #해당 노드와 연결된, 방문하지 않은 원소들을 큐에 삽입
        for i in graph[v]:
            if not visited[i]:
                queue.append(i)
                visited[i] = True
# 각 노드가 연결된 정보
graph = [
    [],
    [2,4],
    [1, 5, 6],
    [4],
    [1, 3, 5],
    [2, 4, 7],
    [2, 7],
    [5, 6],
]

# 노드 방문 정보 초기화
visited = [False] * 8

bfs(graph, 1, visited)

 

Comments