ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • DFS, BFS
    Programming/leetcode 2021. 2. 23. 22:44
    728x90

    그래프 순회 이론 정리

     

    DFS - 깊이 우선 탐색, Stack과 재귀 호출로 구현되며 Back-Tracking과 같이 사용하면 뛰어난 효과

    BFS - 너비 우선 탐색, 주로 Queue로 구현하며 최단 경로 문제에서 많이 사용됨(다익스트라 알고리즘)

     

    코딩테스트에서 대부분의 그래프 탐색은 DFS로 이루어짐

     

    DFS 

    - Stack과 재귀 호출로 구현

     

    ex) 

    graph = { 1:[2,3,4], 2:[5], 3:[5], 4:[], 5:[6,7], 6:[], 7:3}

     

    재귀 호출로 구현 

    
    graph = { 1:[2,3,4], 2:[5], 3:[5], 4:[], 5:[6,7], 6:[], 7:[3]}
    
    def recursive_dfs(v, discovered=[]):
        discovered.append(v)
    
        for w in graph[v]:
            if w not in discovered:
                discovered = recursive_dfs(w, discovered)
        return discovered
    
    
    print(f'recursive dfs : {recursive_dfs(1)}')
    # recursive dfs : [1, 2, 5, 6, 7, 3, 4]

    1번->2번->5번->6번->7번->3번->4번 순으로 방문하게 된다

     

    Stack 구현

    def iterative_dfs(start_v):
        stack = [start_v]
        discovered = []
        while stack:
            v = stack.pop()
            if v not in discovered:
                discovered.append(v)
                for w in graph[v]:
                    stack.append(w)
        return discovered
    
    print(f'recursive dfs : {iterative_dfs(1)}')
    #recursive dfs : [1, 4, 3, 5, 7, 6, 2]

    최초의 정점을 stack에 넣고 while문에서 해당 정점과 연결된 자식 node를 전부 넣는다. 

    그리고 다시 stack에서 자식을 하나씩 꺼내서 해당 자식의 node를 방문한다. 

     

    stack이기때문에 LIFO정책으로 1 다음에는 4가 온다.

     

    백트래킹 

    - 탐색을 하다가 더 갈 수 없을때 왔던 길을 되돌아가 다른 길을 찾는 방법

    - 주로 재귀로 구현되며, DFS와 같이 많이 쓰임

    - 한번 방문 후, 가능성이 없으면 표시를 해두고 다시 가지 않도록 하면 성능이 많이 향상된다

     

    BFS

    - Queue로 구현, 최단경로를 찾는 다익스트라 문제에서 많이 사용됨

    - 옆의 node를 먼저 검색한다.

     

    def iterative_bfs(start_v):
        discovered = [start_v]
        queue = [start_v]
    
        while queue:
            v = queue.pop(0)
            for w in graph[v]:
                if w not in discovered:
                    discovered.append(w)
                    queue.append(w)
        return discovered
    
    print(f'iterative_bfs  : {iterative_bfs(1)}')
    # iterative_bfs  : [1, 2, 3, 4, 5, 6, 7]

     

     

    graph = {1:[2,3,4], 2:[5], 3:[5], 4:[],5:[6,7], 6:[], 7:[3]}
    
    #recursive dfs
    def recursive_dfs(v, discovered=[]):
        discovered.append(v)
    
        for w in graph[v]:
            if w not in discovered:
                discovered = recursive_dfs(w, discovered)
        return discovered
    
    
    #iterative dfs
    def iterative_dfs(start_v):
        stack =[start_v]
        discovered = []
    
        while stack:
            v = stack.pop()
            if v not in discovered:
                discovered.append(v)
                for w in graph[v]:
                    stack.append(w)
        return discovered
    
    #iterative_bfs
    def iterative_bfs(start_v):
        queue = collections.deque()
    
        queue.append(start_v)
        discovered = []
        while queue:
            v = queue.popleft()
            if v not in discovered:
                discovered.append(v)
                for w in graph[v]:
                    queue.append(w)
        return discovered
    

    'Programming > leetcode' 카테고리의 다른 글

    17. Letter Combinations of a Phone Number  (0) 2021.02.24
    200. Number of Islands  (0) 2021.02.24
    347. Top K Frequent Elements  (0) 2021.02.22
    3. Longest Substring Without Repeating Characters  (0) 2021.02.22
    771. Jewels and Stones  (0) 2021.02.22
Designed by Tistory.