모든 노드를 빠짐 없이 탐색하는 방법은 두 가지가 있다.
- 깊이 우선 탐색(Depth First Search, DFS)
- 너비 우선 탐색 (Breadth First Search, BFS)
1. 트리 탐색
의사 코드
DFS(v){
stack.push(v)
while(! stack.isEmpty){
curr = stack.pop
for w in (curr의 모든 자식)
stack.push(w)
}
}
2. 재귀 함수를 통한 트리 검색
이런 경우, 방문을 처리하기 위한 boolean 함수를 사용해주면 된다.
예시
import java.util.Scanner;
public class 그래프탐색01_DFS {
static int V, E; // 정점의 갯수, 간선의 갯수
static int[][] adj; // 인접행렬
static boolean[] visited; // 방문 체크
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
V = sc.nextInt();
E = sc.nextInt();
adj = new int[V+1][V+1]; // 시작 정점의 번호가 1부터 시작하기 때문에
visited = new boolean[V+1];
for(int i = 0; i < E; i++) {
int A = sc.nextInt();
int B = sc.nextInt();
adj[A][B] = 1;
adj[B][A] = 1; // 간선 입력 완료
}
DFS(1);
}
// v: 현재 내가 있는 정점
static void DFS(int v) {
visited[v] = true;
System.out.println(v + " -> ");
// 나와 인접하면서 방문하지 않는 정점 방문
for(int i = 1; i <= V; i++) {
// 방문 여부 인접 여부 체크
if(!visited[i] && adj[v][i] == 1) {
DFS(i);
}
}
}
}
3. 미로 찾기(배열 탐색)
이동 시에 이미 갔던 곳과, 미로의 이동 가능 경로, 그 후에 다른 조건들을 탐색하며 돌아가게 된다.
이동 경로는 nr = r + dr[i]
가 되고, nc = c + dc[i]
라는 방식으로 상하좌우 탐색.
하면서 if(nr < 0 || nr >= N || nc < 0 || nc >= N)
과 같이 경계를 확인하면 된다.
1. 트리 탐색
수도코드
BFS(v){
Queue 생성
Queue.add(v)
while (!Queue.isEmpty()){
curr ← Queue.deq()
curr 방문
for w in (curr의 모든 자식 노드){
Queue.add(w)
}
}
}
2. 그래프 탐색 실습
자바 구현
public class 그래프탐색01_DFS {
static int V, E; // 정점의 갯수, 간선의 갯수
static List<Integer>[] adj; // 인접 리스트
static boolean[] visited; // 방문 체크
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
V = sc.nextInt();
E = sc.nextInt();
// adj = new ArrayList[V+1]; 배열만 생성한 것이고, 안에 리스트 생성 필요
for(int i = 1; i < V; i++) { // 1번 정점부터 시작하기 때문에
adj[i] = new ArrayList<>();
}
visited = new boolean[V+1];
for(int i = 0; i < E; i++) {
int A = sc.nextInt();
int B = sc.nextInt();
adj[A].add(B);
adj[B].add(A);
}
}
// 시작 정점 v 삽입
static void BFS(int v) {
Queue<Integer> q = new LinkedList<>();
// 시작 정점을 넣고, 방문을 체크한다.
q.add(v);
visited[v] = true;
// 큐가 공백 상태가 아닐 때까지 돌겠다는 의미
while(!q.isEmpty()) {
int curr = q.poll(); // 정점을 한 개 꺼낸다.
System.out.println(curr);
// curr의 인접하면서 방문하지 않은 정점을 방문
for(int w : adj[curr]) {
if (!visited[w]) {
q.add(w);
visited[w] = true;
}
}
/* for(int i = 0; i < adj[curr].size(); i++){
int w = adj[curr].get(i)
}
와 동일하다.
*/
}
}
}
3. 미로 찾기(배열 탐색)
nr = curr.r + dr[i]
, nc = curr.c + dc[i]
라는 좌표를 갖는다.