[JAVA] 너비 우선 탐색(BFS, Breadth-First Search)

2025. 2. 15. 13:36·코테/알고리즘
728x90

BFS: 너비우선탐색

탐색과정

  1. 시작하는 칸을 큐에 넣고 방문했다는 표시를 남김
  2. 큐에서 원소를 꺼내어 그 칸에 상하좌우로 인접한 칸에 대해 3번을 진행
  3. 해당 칸을 이전에 방문했다면 아무 것도 하지 않고, 처음으로 방문했다면 방문했다는 표시를 남기고 해당 칸을 큐에 삽입
  4. 큐가 빌 때까지 2번을 반복

처음 방문 했을 때만 방문 표시를 남기기 때문에 모든 칸이 큐에 1번씩 들어간다. 따라서 시간복잡도는 칸이 N개일 때 O(N)이다. 같은 원리로 행이 R개, 열이 C개인 2차원 평면을 BFS 탐색하면 시간복잡도는 O(RC)가 될 것이다.

dx, dy 상하좌우

 

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 = {-1, 1, 0, 0};
    static int[] dy = {0, 0, -1, 1}; // 상하좌우 

    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;
        }
    }
}

잘못된 경우

  1. 시작점에 방문했다는 표시를 남기지 않는다.
  2. 큐를 넣을 때 방문했다는 표시를 하는 대신 큐에서 빼낼 때 방문했다는 표시를 남겼다.
  3. 이웃한 원소가 범위를 벗어났는지에 대한 체크를 잘못했다.

너비 우선 탐색

-루트 노드(혹은 다른 임의의 노드)에서 시작해서 인접한 노드를 먼저 탐색하는 방법
-시작 정점으로부터 가까운 정점을 먼저 방문하고 멀리 떨어져 있는 정점을 나중에 방문하는 순회 방법이다.
즉, 깊게(deep) 탐색하기 전에 넓게(wide) 탐색하는 것이다.
사용하는 경우: 두 노드 사이의 최단 경로 혹은 임의의 경로를 찾고 싶을 때 이 방법을 선택한다.

vs dfs

728x90
반응형

'코테 > 알고리즘' 카테고리의 다른 글

[JAVA] 그리디(Greedy)  (0) 2025.02.15
[JAVA] 다이나믹 프로그래밍(DP)  (0) 2025.02.15
[JAVA] 백트래킹(Backtracking)  (0) 2025.02.15
[JAVA] 깊이 우선 탐색(DFS, Depth-First Search)  (0) 2025.02.15
[JAVA] 스택(Stack)과 큐(Queue)  (0) 2025.02.15
'코테/알고리즘' 카테고리의 다른 글
  • [JAVA] 다이나믹 프로그래밍(DP)
  • [JAVA] 백트래킹(Backtracking)
  • [JAVA] 깊이 우선 탐색(DFS, Depth-First Search)
  • [JAVA] 스택(Stack)과 큐(Queue)
lakedata
lakedata
lakedata 님의 블로그 입니다.
  • lakedata
    lakedata 님의 블로그
    lakedata
  • 전체
    오늘
    어제
    • 분류 전체보기 (188)
      • cs (82)
        • dev (28)
        • sec (29)
        • ops (25)
      • 자격증 (32)
        • 정보처리기사 (20)
        • 정보보안기사 (1)
        • aws dva (6)
        • aws dop (2)
      • IT서적 (27)
        • 클린아키텍처 (10)
        • 객체지향의사실과오해 (7)
        • 오브젝트 (10)
      • 코테 (42)
        • 알고리즘 (20)
        • 백준 (13)
        • 프로그래머스 (7)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • github
  • 공지사항

  • 인기 글

  • 태그

    SQL
    docker
    Spring
    CS
    Java
    Security
    AWS
    알고리즘
  • 최근 댓글

  • 최근 글

  • 반응형
    250x250
  • hELLO· Designed By정상우.v4.10.3
lakedata
[JAVA] 너비 우선 탐색(BFS, Breadth-First Search)
상단으로

티스토리툴바