🥞 BE
home

DFS / BFS

DFS - 깊이 우선 탐색 / BFS - 너비 우선 탐색

DFS(Depth First Search)
BFS(Breadth First Search)
1) 방문 리스트 : 방문 처리 목적 / 정점의 개수만큼 길이 생성
visited = [0] * 정점의 개수
2) 인접 행렬 / 인접 리스트 : 노드, 간선 연결 저장
3) stack / queue : 실시간 현황
자료구조 : 스택 (선입후출)
1.
루트 노드를 스택에 넣고 방문 처리 한다.
2.
스택 최상단 노드의 인접 노드 중 방문하지 않은 노드 하나를 스택에 넣고 방문 처리한다. 만약 인접 노드를 모두 방문한 경우 스택을 Pop 한다.
3.
2 단계를 더 이상 수행할 수 없을 때 까지 (스택이 빌 때 까지) 반복한다.
자료구조 : 큐 (선입선출)
1.
루트 노드를 큐에 넣고 방문 처리한다.
2.
방문 처리한 노드를 큐에서 제거하고, 제거한 노드의 방문하지 않은 모든 인접 노드를 큐에 넣고 방문 처리한다.
3.
2 단계를 더 이상 수행할 수 없을 때 까지 (큐가 빌 때 까지) 반복한다.

DFS / BFS 예제

DFS 예제
# 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(graph, 1, visited) # 출력 1 2 7 6 8 3 4 5
Python
복사
BFS 예제
from collections import deque # BFS 메서드 정의 def bfs(graph, start, visited): # 큐(Queue) 구현을 위해 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] ] visited = [False]*9 bfs(graph, 1, visited) # 출력 1 2 3 8 7 4 5 6
Python
복사

인접 행렬 / 인접 리스트

1) 인접 행렬 : 행렬로 정점들 사이의 관계를 표현하는 방식
2) 인접 리스트 : 각 정점에 연결된 노드들의 정보를 저장하는 방식
시간복잡도
인접 리스트 : O(V + E)
인접 행렬 : O(V^2)
/* 인접 리스트 이용 */ class Graph { private int V; private LinkedList<Integer> adj[]; Graph(int v) { V = v; adj = new LinkedList[v]; // 인접 리스트 초기화 for (int i=0; i<v; ++i) adj[i] = new LinkedList(); } void addEdge(int v, int w) { adj[v].add(w); } /* DFS에 의해 사용되는 함수 */ void DFSUtil(int v, boolean visited[]) { // 현재 노드를 방문한 것으로 표시하고 값을 출력 visited[v] = true; System.out.print(v + " "); // 방문한 노드와 인접한 모든 노드를 가져온다. Iterator<Integer> it = adj[v].listIterator(); while (it.hasNext()) { int n = it.next(); // 방문하지 않은 노드면 해당 노드를 시작 노드로 다시 DFSUtil 호출 if (!visited[n]) DFSUtil(n, visited); } } /* DFS */ void DFS(int v) { boolean visited[] = new boolean[V]; // v를 시작 노드로 DFSUtil 재귀 호출 DFSUtil(v, visited); } }
Java
복사
class Graph { private int V; private LinkedList<Integer> adj[]; Graph(int v) { V = v; adj = new LinkedList[v]; for (int i=0; i<v; ++i) adj[i] = new LinkedList(); } void addEdge(int v, int w) { adj[v].add(w); } /* BFS */ void BFS(int s) { boolean visited[] = new boolean[V]; LinkedList<Integer> queue = new LinkedList<Integer>(); visited[s] = true; queue.add(s); while (queue.size() != 0) { // 방문한 노드를 큐에서 추출(dequeue)하고 값을 출력 s = queue.poll(); System.out.print(s + " "); // 방문한 노드와 인접한 모든 노드를 가져온다. Iterator<Integer> i = adj[s].listIterator(); while (i.hasNext()) { int n = i.next(); // 방문하지 않은 노드면 방문한 것으로 표시하고 큐에 삽입(enqueue) if (!visited[n]) { visited[n] = true; queue.add(n); } } } }
Java
복사

Reference