BFS : 그래프에서의 너비 우선 탐색 알고리즘
DFS와 다르게 가까운 곳부터 차례대로 탐색하는 알고리즘이다.
(DFS는 한 방향으로 끝까지 탐색한 뒤 돌아가는 방식)
BFS 알고리즘 코드 템플릿
자다가도 벌떡 일어나서 짤 수 있어야 훌륭한 개발자가 된다고 한다.
import java.util.*;
public class Main {
// 1이 파란 칸, 0이 빨간 칸에 대응
// 실제로 문제를 풀 때는 2차원 배열을 콘솔에서 입력을 받는다.
static int[][] board = {
{1,1,1,0,1,0,0,0,0,0},
{1,0,0,0,1,0,0,0,0,0},
{1,1,1,0,1,0,0,0,0,0},
{1,1,0,0,1,0,0,0,0,0},
{0,1,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0}
};
// 해당 칸을 방문했는지 여부를 저장, boolean 2차원 배열로 선언, 주로 board와 같은 사이즈로 만든다.
static int n = 7, m = 10; // n = 행의 수, m = 열의 수
static boolean[][] visited = new boolean[n][m];
static int[] dx = {1, 0, -1, 0}; // dx, dy 의 d는 변하는 값을 의미
static int[] dy = {0, 1, 0, -1}; // 상하좌우 네 방향을 의미
public static void main(String[] args) {
Queue<Pair> Q = new ArrayDeque<>();
visited[0][0] = true; // (0, 0)을 방문했다고 명시
Q.offer(new Pair(0, 0)); // 큐에 시작점인 (0, 0)을 삽입
while (!Q.isEmpty()) {
Pair cur = Q.poll();
int curX = cur.x;
int curY = cur.y;
// 디버깅용 로그
System.out.print("(" + curX + ", " + curY + ") -> ");
for (int i = 0; i < 4; i++) { // 상하좌우 칸을 살펴볼 것이다, 상 하 좌 우 총 4회 반복
int nx = curX + dx[i]; // nx, ny 의 n은 next
int ny = curY + dy[i]; // nx, ny에 i에서 정한 방향의 인접한 칸의 좌표가 들어감
// i = 0 일땐 nx = 1, ny = 0 => 현재 좌표에서 x축으로 1, y축으로 0 이동한 칸 (오른쪽 칸)
// i = 1 일땐 nx = 0, ny = 1 => 현재 좌표에서 x축으로 0, y축으로 1 이동한 칸 (아래 칸)
// i = 2 일땐 nx = -1, ny = 0 => 현재 좌표에서 x축으로 -1, y축으로 0 이동한 칸 (왼쪽 칸)
// i = 3 일땐 nx = 0, ny = -1 => 현재 좌표에서 x축으로 0, y축으로 1 이동한 칸 (윗 칸)
// nx, ny 좌표 유효성 검증
if (nx < 0 || nx >= n || ny < 0 || ny >= m) continue; // 범위 밖일 경우 넘어감
if (visited[ny][nx] || board[ny][nx] != 1) continue; // 이미 방문한 칸이거나 파란 칸이 아닐 경우
visited[ny][nx] = true; // (nx, ny)를 방문했다고 명시
Q.offer(new Pair(nx, ny));
}
}
}
static class Pair {
int x;
int y;
// int distance; 문제에 따라 거리 변수, 시간 변수, cnt 변수 등 값들이 추가로 들어간다.
Pair (int x, int y) {
this.x = x;
this.y = y;
}
}
}
<BFS 알고리즘을 구현할 때 주의해야 할 사항>
- 시작점 위치를 방문 표시하기
- 큐에서 빼낼 때 방문 표시를 하지 말고 큐에 넣을 때 방문 표시 하기
(같은 칸이 큐에 여러 번 들어가게 되면서 시간 초과, 메모리 초과가 발생할 수 있다.
- 인접 원소가 범위를 벗어나지 않았는지 잘 확인하기
- x, y, 행, 열 주의
BFS 알고리즘을 사용해야 하는 경우
- "최소", "최단", "가장 빠른" 키워드
- 시작점에서 거리별로 정보가 필요할 때
- 답이 비교적 가까운 곳에 있을 때
- 최단 경로(미로 탈출, 네트워크에서의 최소 홉 수), 레벨 별 탐색(트리의 레벨 순회), 넓게 퍼져서 찾는 것이 효율적일 때
DFS : 그래프에서의 깊이 우선 탐색 알고리즘
DFS 알고리즘 코드 템플릿
import java.util.*;
public class Main {
static int[][] board = {
{1,1,1,0,1,0,0,0,0,0},
{1,0,0,0,1,0,0,0,0,0},
{1,1,1,0,1,0,0,0,0,0},
{1,1,0,0,1,0,0,0,0,0},
{0,1,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0}
}; // 1이 파란 칸, 0이 빨간 칸
static boolean[][] vis = new boolean[502][502]; // 방문 여부
static int n = 7, m = 10; // 행, 열
static int[] dx = {1,0,-1,0};
static int[] dy = {0,1,0,-1}; // 상하좌우
public static void main(String[] args) {
Stack<int[]> S = new Stack<>();
vis[0][0] = true; // 시작점 방문 처리
S.push(new int[]{0, 0});
while(!S.isEmpty()) {
int[] cur = S.pop();
System.out.print("(" + cur[0] + ", " + cur[1] + ") -> ");
for(int dir = 0; dir < 4; dir++) {
int nx = cur[0] + dx[dir];
int ny = cur[1] + dy[dir];
if(nx < 0 || nx >= n || ny < 0 || ny >= m) continue; // 범위 체크
if(vis[nx][ny] || board[nx][ny] != 1) continue; // 방문했거나 파란 칸 아니면 skip
vis[nx][ny] = true;
S.push(new int[]{nx, ny});
}
}
}
}
BFS에서 큐를 스택으로 변경하면 DFS가 된다.
한 방향으로 먼저 끝까지 탐색한 뒤 다른 방향으로 탐색한다.
스택을 이용한 DFS, 재귀를 이용한 DFS가 있다.
DFS + 백트래킹 유형으로 자주 나온다.
'CS' 카테고리의 다른 글
| [DB] SubQuery 1 (0) | 2026.02.09 |
|---|---|
| [DB] MySQL 성능 최적화 (0) | 2025.12.07 |
| [네트워크] 쿠키, 세션 (0) | 2025.11.02 |
| [운영체제] Java와 고성능 게임 개발 (0) | 2025.09.04 |
| [네트워크] OSI 7계층 (0) | 2025.09.03 |