Python으로 DFS, BFS 구현

3Juhwan·2021년 2월 20일
0

Algorithm

목록 보기
4/23

🎨 단순한 구현

반복문으로 구현해서 DFS/BFS를 이해하기 쉽다!


다음은 dictlist를 이용한 탐색할 graph 이다.

graph = {
    'A': ['B'],
    'B': ['A', 'C', 'H'],
    'C': ['B', 'D'],
    'D': ['C', 'E', 'G'],
    'E': ['D', 'F'],
    'F': ['E'],
    'G': ['D'],
    'H': ['B', 'I', 'J', 'M'],
    'I': ['H'],
    'J': ['H', 'K'],
    'K': ['J', 'L'],
    'L': ['K'],
    'M': ['H']
}

DFS

liststack의 용도로 쓰고 있다.

  1 def dfs(graph, start_node):
  2     visit = list()
  3     stack = list()
  4
  5     stack.append(start_node)
  6
  7     while stack:
  8         node = stack.pop()
  9         if node not in visit:
 10             visit.append(node)
 11             stack.extend(graph[node])
 12
 13     return visit

BFS

listqueue의 용도로 쓰고 있다.

  1 def bfs(graph, start_node):
  2     visit = list()
  3     queue = list()
  4
  5     queue.append(start_node)
  6
  7     while queue:
  8         node = queue.pop(0)
  9         if node not in visit:
 10             visit.append(node)
 11             queue.extend(graph[node])
 12
 13     return visit

한계점

위 코드는 효율성이 많이 떨어진다.

1. bfs에서 queuepythonqueue를 사용하는 게 효율적이다.

pythonliststack처럼 사용된다.
bfs 코드에서는 stackqueue로 사용해서 pop(0)을 하는데,
pop(0)의 시간 복잡도는 O(n)이기 때문에 비효율적이다.

2. visitlist 대신 setdict를 사용하는 효율적이다.

python에서 dictHash table 역할을 한다. 원소의 중복 여부를 key로 탐색하기에 평균 O(1)의 시간 복잡도를 갖는다.


🎨 보완

programiz 사이트에서 괜찮은 코드를 찾을 수 있었다.


BFS

list 대신 collections 모듈의 deque를 이용한다.
visitedset로 구현한다.

import collections

# BFS algorithm
def bfs(graph, root):

   visited, queue = set(), collections.deque([root])
   visited.add(root)

   while queue:

       # Dequeue a vertex from queue
       vertex = queue.popleft()
       print(str(vertex) + " ", end="")

       # If not visited, mark it as visited, and
       # enqueue it
       for neighbour in graph[vertex]:
           if neighbour not in visited:
               visited.add(neighbour)
               queue.append(neighbour)


if __name__ == '__main__':
   graph = {0: [1, 2], 1: [2], 2: [3], 3: [1, 2]}
   print("Following is Breadth First Traversal: ")
   bfs(graph, 0)

시간 복잡도는 O(V + E)Vnode 개수이고, Eedge 개수이다.


DFS

재귀로 구현한 코드이다.
visitedset로 구현한다.

# DFS algorithm
def dfs(graph, start, visited=None):
   if visited is None:
       visited = set()
   visited.add(start)

   print(start)

   for next in graph[start] - visited:
       dfs(graph, next, visited)
   return visited


graph = {'0': set(['1', '2']),
        '1': set(['0', '3', '4']),
        '2': set(['0']),
        '3': set(['1']),
        '4': set(['2', '3'])}

dfs(graph, '0')

시간 복잡도는 O(V + E)Vnode 개수이고, Eedge 개수이다.


✨ 내가 작성한 코드

재귀를 이용해서 DFS를 작성해봤다.
위의 graph를 사용했다.

def dfs(graph, start_node, visit=list()):
   visit.append(start_node)
   print(start_node, end=' ')
   
   for node in graph[start_node]:
       if node not in visit:
           dfs(graph, node, visit)

dfs(graph, 'A')

>> A B C D E F G H I J K L M

🎁 Reference

profile
Codeforces와 USACO 풀이를 기록합니다. 이전 글도 계속 업데이트 됩니다.

0개의 댓글