CH5) DFS / BFS

cheeeese·2022년 1월 24일
0

공부

목록 보기
4/6
post-thumbnail

책 정리

꼭 필요한 자료구조 기초

✔ 탐색

  • 많은 양의 데이터 중에서 원하는 데이터를 찾는 과정
  • 대표적으로 DFS, BFS

✔ 자료구조

  • 데이터를 표현하고 관리하고 처리하기 위한 구조
  • 기초 개념으로 스택,
    -> 삽입(Push): 데이터를 삽입한다
    -> 삭제(Pop): 데이터를 삭제한다

📌 스택 (Stack)

  • 선입후출구조 (First In Last Out) 또는 후입선출구조(Last In Fisrt Out)
  • 별도의 라이브러리 사용할 필요 없이 기본 리스트에서 append()pop() 메서드를 이용하면 스택 자료구조와 동일하게 동작
    • append(): 리스트 가장 뒤쪽에 데이터 삽입
    • pop(): 리스트의 가장 뒤쪽에서 데이터 꺼냄

📌 큐(Queue)

  • 선입선출 구조 (First In First Out)
  • 삽입: append()
  • 삭제: popleft()
  • 파이썬에서 큐를 구현할 때는 collections 모듈에서 제공하는 deque 자료구조 활용
    • deque: 스택과 큐의 장점을 모두 채택한 것으로 데이터를 넣고 빼는 속도가 리스트 자료형에 비해 효율적이며 queue 라이브러리를 이용하는 것보다 더 간단
    • from collections import deque

큐 예제

from collections import deque

# 큐 구현을 위해 deque 라이브러리 사용
queue = deque()

queue.append(5)
queue.append(2)
queue.append(3)
queue.append(7)
queue.popleft()
queue.append(1)
queue.append(4)
queue.popleft()

print(queue) # 먼저 들어온 순서대로 출력
queue.reverse() # 역순으로 바꾸기
print(queue)

결과

deque([3, 7, 1, 4])
deque([4, 1, 7, 3])

📌 재귀 함수

  • 자기 자신을 다시 호출하는 함수
  • 재귀함수를 문제 풀이에서 사용 할 때는 if 문을 이용하여 종료 조건을 꼭 명시해야 한다

탐색 알고리즘 DFS/BSF

📌 DFS

  • Depth-First Search 깊이 우선 탐색
  • 그래프에서 깊은 부분을 우선적으로 탐색하는 알고리즘
  • 그래프 - 노드(Node) 또는 정점(Vertex)간선(Edge)로 표현
  • 그래프 탐색: 하나의 노드를 시작으로 다수의 노드를 방문하는 것

그래프 표현 방식

  • 인접 행렬(Adjacency Matrix)

    • 2차원 배열로 그래프의 연결관계 표현
    • 연결된 그래프를 인접 행렬로 표현할 때 파이썬에서는 2차원 리스트로 구현할 수 있다
    • 연결이 되어있지 않은 노드끼리는 무한의 비용이라고 작성
  • 인접 리스트(Adjacency List)

    • 리스트로 그래프의 연결관계 표현
    • 모든 노드에 연결된 노드에 대해 정보를 차례대로 연결하여 저장
    • 연결 리스트 이용해 구현
      -> 파이썬으로 인접리스트 이용해 그래프를 표현하고자 할 때엔 단순히 2차원 리스트만 이용하면 됨

두 방식의 차이점은?

  • 인접 행렬 방식은 모든 관계를 저장하므로 노드 개수가 많을수록 메모리가 불필요하게 낭비

  • 인접 리스트 방식은 연결된 정보만을 저장하기 때문에 메모리를 효율적 사용

    • 연결된 데이터를 하나씩 확인해야 하기 때문에 특정한 두 노드가 연결되어 있는지에 대한 정보를 얻는 속도가 느리다

DFS의 구체적인 동작과정

  1. 탐색 시작 노드를 스택에 삽입하고 방문 처리를 한다
  2. 스택의 최상단 노드에 방문하지 않은 인접 노드가 있으면 그 인접 노드를 스택에 넣고 방문 처리를 한다. 방문하지 않은 인접노드가 없으면 스택에서 최상단 노드를 꺼낸다
  3. 2번의 과정을 더 이상 수행할 수 없을 때까지 반복한다
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, 3, 8],
    [1, 7],
    [1, 4, 5],
    [3, 5],
    [3, 4],
    [7],
    [2, 6, 8],
    [1, 7]
]

visited = [False]*9
dfs(graph, 1, visited)

출력

1 2 7 6 8 3 4 5

📌 BFS

  • Breadth First Search 너비 우선 탐색
  • 가까운 노드부터 탐색
  • 선입선출 방식인 큐 자료구조를 이용하는 것이 정석

동작방식
1. 탐색 시작 노드를 큐에 삽입하고 방문 처리
2. 큐에서 노드를 꺼내 해당 노드의 인접 노드 중에서 방문하지 않은 노드를 모두 큐에 삽입하고 방문 처리
3. 2번의 과정을 더 이상 수행할 수 없을 때까지 반복

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, 3, 8],
    [1, 7],
    [1, 4, 5],
    [3, 5],
    [3, 4],
    [7],
    [2, 6, 8],
    [1, 7]
]

visited = [False]*9
bfs(graph, 1, visited)

출력

1 2 3 8 7 4 5 6 

DFS

  • 동작 원리: 스택
  • 구현 방법:재귀함수 이용

BFS

  • 동작 원리: 큐
  • 구현 방법: 큐 자료구조 이용

실전 문제

음료수 얼려먹기

0개의 댓글