BFS: 너비우선탐색
처음 방문 했을 때만 방문 표시를 남기기 때문에 모든 칸이 큐에 1번씩 들어간다. 따라서 시간복잡도는 칸이 N개일 때 O(N)이다. 같은 원리로 행이 R개, 열이 C개인 2차원 평면을 BFS 탐색하면 시간복잡도는 O(RC)가 될 것이다.
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; // n = 행의 수, m = 열의 수
static int[] dx = {0, 0, -1, 1};
static int[] dy = {-1, 1, 0, 0}; // 상하좌우
public static void main(String[] args) {
bfs(0, 0); // 시작점 (0, 0)에서 BFS 시작
}
// bfs 함수로 따로 분리
static void bfs(int startX, int startY) {
Queue<Pair> que = new LinkedList<>();
vis[startX][startY] = true; // 시작점을 방문했다고 명시
que.add(new Pair(startX, startY)); // 큐에 시작점 삽입
while (!que.isEmpty()) {
Pair cur = que.poll(); // 큐에서 현재 좌표를 가져옴
System.out.print("(" + cur.x + ", " + cur.y + ") -> ");
for (int dir = 0; dir < 4; dir++) { // 상하좌우 칸을 탐색
int nx = cur.x + dx[dir];
int ny = cur.y + dy[dir]; // nx, ny에 dir 방향의 인접한 칸의 좌표가 들어감
if (nx < 0 || nx >= n || ny < 0 || ny >= m) continue; // 범위를 벗어나면 무시
if (vis[nx][ny] || board[nx][ny] != 1) continue; // 이미 방문했거나 파란 칸이 아닐 경우 무시
vis[nx][ny] = true; // (nx, ny)를 방문했다고 명시
que.add(new Pair(nx, ny)); // 큐에 새로 방문한 좌표를 추가
}
}
}
// 좌표를 저장하는 Pair 클래스
static class Pair {
int x, y;
Pair(int x, int y) {
this.x = x;
this.y = y;
}
}
}
-루트 노드(혹은 다른 임의의 노드)에서 시작해서 인접한 노드를 먼저 탐색하는 방법
-시작 정점으로부터 가까운 정점을 먼저 방문하고 멀리 떨어져 있는 정점을 나중에 방문하는 순회 방법이다.
즉, 깊게(deep) 탐색하기 전에 넓게(wide) 탐색하는 것이다.
사용하는 경우: 두 노드 사이의 최단 경로 혹은 임의의 경로를 찾고 싶을 때 이 방법을 선택한다.