ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Ch5 DFS/BFS
    [이것이 취업을 위한 코딩테스트다 with 파이썬]/코딩 테스트를 위한 파이썬 문법 2023. 5. 3. 22:11

    꼭 필요한 자료구조 기초

    • 탐색: 많은 양의 데이터 중에서 원하는 데이터를 찾는 과정. 대표적인 탐색 알고리즘 → DFS/BFS
    • 스택: LIFO, 파이썬에서 스택 이용할 때에는 별도 라이브러리 사용할 필요 없이 기본 리스트의 append()와 pop() 메서드 이용
    stack = []
    
    stack.append(5)
    stack.pop()
    
    print(stack) # 최하단 원소부터 출력
    print(stack[::-1]) # 최상단 원소부터 출력
    • 큐: FIFO, '공정한' 자료구조, 파이썬으로 큐를 구현할 때는 collections 모듈에서 제공하는 deque 자료구조 활용
    • deque 객체를 리스트 자료형으로 변경하고자 한다면 list() 메서드 이용
    from collections import deque
    
    queue = deque()
    
    queue.append(5)
    queue.append(2)
    queue.popleft()
    
    print(queue)    # 먼저 들어온 순서대로 출력
    queue.reverse() # 다음 출력을 위해 역순으로 바꾸기
    print(queue)    # 나중에 들어온 원소부터 출력
    • 재귀 함수: 자기 자신을 다시 호출하는 함수. 종료 조건을 꼭 명시해야 한다. 재귀 함수는 내부적으로 스택 자료구조와 동일
    def factorial_iterative(n):
        result = 1
        for i in range(1, n+1):
            result *= i
        return result
        
    def factorial_recursive(n):
    	if n <= 1:
        	return 1
        return n * factorial_recursive(n-1)

    탐색 알고리즘 DFS/BFS

    그래프를 표현하는 2가지 방식

    • 인접 행렬: 2차원 배열로 그래프의 연결 관계를 표현하는 방식
    INF = 999999999 # 무한의 비용 선언
    
    graph = [
    	[0, 7, 5],	
    	[7, 0, INF],
    	[5, INF, 0]
    ]
    
    print(graph)
    • 인접 리스트: 리스트로 그래프의 연결 관계를 표현하는 방식. 2차원 리스트를 이용하면 된다.
    # 행이 3개인 2차원 리스트로 인접 리스트 표현
    graph = [[] for _ in range(3)]
    
    # 노드 0에 연결된 노드 정보 저장(노드, 거리)
    graph[0].append((1, 7))
    graph[0].append((2, 5))
    
    # 노드 1에 연결된 노드 정보 저장(노드, 거리)
    graph[1].append((0, 7))
    
    # 노드 2에 연결된 노드 정보 저장(노드, 거리)
    graph[2].append((0, 5))
    
    print(graph)

     

    DFS(Depth-First Search, 깊이 우선 탐색): 그래프에서 깊은 부분을 우선적으로 탐색하는 알고리즘

    구체적인 동작 과정(스택 자료구조에 기초), 데이터의 개수가 N개인 경우 O(N)의 시간 소요

    1. 탐색 시작 노드를 스택에 삽입하고 방문 처리를 한다.
    2. 스택의 최상단 노드에 방문하지 않은 인접 노드가 있으면 그 인접 노드를 스택에 넣고 방문 처리를 한다. 방문하지 않은 인접 노드가 없으면 스택에서 최상단 노드를 꺼낸다.
    3. 2번의 과정을 더 이상 수행할 수 없을 때까지 반복한다.
    # DFS 메서드 정의
    def dfs(graph, v, visited):
        # 현재 노드를 방문 처리
        visited[v] = True
        print(v, end=' ')
        # 현재 노드와 연결된 다른 노드를 재귀적으로 방문
        for i in graph[v]:
        	if not visited[i]:
            	dfs(graph, i, visited)
                
    # 각 노드가 연결된 정보를 리스트 자료형으로 표현(2차원 리스트)
    graph = [
        [],
        [2, 3, 8],
        [1, 7],
        [1, 4, 5],
        [3, 5],
        [3, 4],
        [7],
        [2, 6, 8],
        [1, 7]
    ]
    
    # 각 노드가 방문된 정보를 리스트 자료형으로 표현(1차원 리스트)
    visited = [False] * 9
    
    # 정의된 DFS 함수 호출
    dfs(graph, 1, visited)

    BFS(Breadth First Search, 너비 우선 탐색): 가까운 노드부터 탐색하는 알고리즘

    구체적인 동작 과정(큐 자료구조에 기초), 구현은 deque 라이브러리 사용하는 것이 좋으며 탐색 시 O(N) 소요

    일반적인 경우 실제 수행시간은 DFS 보다 좋은 편

    1. 탐색 시작 노드를 큐에 삽입하고 방문 처리를 한다.
    2. 큐에서 노드를 꺼내 해당 노드의 인접 노드 중에서 방문하지 않은 노드를 모두 큐에 삽입하고 방문 처리를 한다.
    3. 2번의 과정을 더 이상 수행할 수 없을 때까지 반복한다.
    from collections import deque
    
    # BFS 메서드 정의
    def bfs(graph, start, visited):
        # 큐 구현을 위해 deque 라이브러리 사용
        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
     
    # 각 노드가 연결된 정보를 리스트 자료형으로 표현(2차원 리스트)
    graph = [
        [],
        [2, 3, 8],
        [1, 7],
        [1, 4, 5],
        [3, 5],
        [3, 4],
        [7],
        [2, 6, 8],
        [1, 7]
    ]
    
    # 각 노드가 방문된 정보를 리스트 자료형으로 표현(1차원 리스트)
    visited = [False] * 9
    
    # 정의된 DFS 함수 호출
    bfs(graph, 1, visited)
Designed by Tistory.