🔷 트리(그래프, 2차원 배열) 순회(탐색)
🔷 루트 노드(시작 정점, 출발 위치)에서 출발하여 한 방향으로 갈 수 있는 경로가 있는 곳까지 깊이 탐색해 가다가 더 이상 갈 곳이 없게 되면, 가장 마지막에 만났던 갈림길 간선이 있는 노드(정점)로 되돌아와서 다른 방향의 노드(정점)으로 탐색을 계속 반복하여 결국 모든 노드(정점)을 방문하는 순회방법
스택
사용🔷 탐색 방법(stack)
1) 루트 노드를 stack에 push한다.
2) stack에서 노드(curr)를 pop한다.
3) curr의 모든 자식 노드를 stack에 push한다.
4) stack이 공백 상태가 될 때까지 2)-3)을 반복한다.
🔷 탐색 방법(재귀 함수)
1) 현재 노드(V) 방문
2) (V)의 자식 노드 (W)를 차례로 재귀 호출
❗ 재귀로 그래프 탐색 시 주의점
1. 트리와 다르게 그래프 탐색 시에는 탐색한 곳을 되돌아가 중복 탐색할 수 있다. 무한 재귀 지옥에 빠질 수 있으므로 visited 처리를 위한 boolean 배열을 따로 선언하여 사용해주자.
2. 인접 행렬 탐색시 범위 체크 중 배열 범위를 벗어날 수 있다. 오류 방지를 위해 2차원 배열의 x, y를 1씩 더 크게 선언한 뒤에 탐색하지 않게 하는 임의의 값을 넣으면 편리하다.
public class DailyAPS {
static int N = 7;
//인접 행렬
static int [][] adj = {
{ 0, 1, 1, 0, 0, 1, 0 },
{ 1, 0, 0, 1, 0, 0, 1 },
{ 1, 0, 0, 1, 0, 0, 0 },
{ 0, 1, 1, 0, 0, 0, 1 },
{ 0, 0, 0, 0, 0, 1, 1 },
{ 1, 0, 0, 0, 1, 0, 0 },
{ 0, 1, 0, 1, 1, 0, 0 }
};
static boolean[] visited = new boolean[N]; //방문처리를 할 배열
public static void main(String[] args) {
DFS(2);
}
//인자로 현재 내가 방문하고 있는 정점이 들어온다.
static void DFS(int v) {
//v에 대한 방문처리
visited[v] = true;
System.out.println(v+1); //그래프가 1부터 시작한다고 가정하고 1을 더했다
//방문하지 않았으면서, 연결된 간선이 존재한다면 재귀 호출
for(int i = 0; i < N; i++) {
if(!visited[i] && adj[v][i] == 1) {
DFS(i);
}
}
}
}
🔷 루트 노드(시작 정점, 출발 위치)의 자식 노드(인접한 정점)들을 먼저 모두 차례로 방문한 후에 방문했던 자식 노드들(인접한 정점)을 시작점으로 하여 다시 해당 노드의 자식 노드(인접한 정점)들을 차례로 방문하는 방식
큐
를 활용🔷 탐색 방법(queue)
1) 루트 노드를 queue에 삽입
2) queue에서 원소(curr) 꺼내기
3) 해당 원소 방문 처리
4) curr의 자식 노드를 queue에 삽입
5) queue가 공백이 될 때까지 2)~5) 반복
import java.util.LinkedList;
import java.util.Queue;
public class DailyAPS {
static int N = 7;
//인접 행렬
static int [][] adj = {
{ 0, 1, 1, 0, 0, 1, 0 },
{ 1, 0, 0, 1, 0, 0, 1 },
{ 1, 0, 0, 1, 0, 0, 0 },
{ 0, 1, 1, 0, 0, 0, 1 },
{ 0, 0, 0, 0, 0, 1, 1 },
{ 1, 0, 0, 0, 1, 0, 0 },
{ 0, 1, 0, 1, 1, 0, 0 }
};
static boolean[] visited = new boolean[N]; //방문처리를 할 배열
static Queue<Integer> queue = new LinkedList<Integer>();
public static void main(String[] args) {
BFS(0);
}
//v: 시작정점
static void BFS(int v) {
//시작정점을 큐에 넣는다.
queue.add(v);
visited[v] = true; //방문처리
//큐가 공백이 될 때까지 반복
while(!queue.isEmpty()) {
//정점을 하나 꺼낸다
int t = queue.poll();
System.out.println(t+1); //1부터 시작한다고 가정
//t와 연결되어 있으면서 방문하지 않는 정점들은 queue에 넣고 방문처리를 한다
for(int i = 1; i < N; i++) {
if(!visited[i] && adj[t][i] == 1) {
queue.add(i); //큐에 넣고 방문처리
visited[i] = true;
}
}
}
}
}
🔷 최단 길이 구하는 방법
1) 2차원 배열을 만들어 직접 길이를 저장한다.
2) 큐에 넣을 때 같이 넣어 저장한다. (큐 생성시 Integer[]로 생성 or 클래스 멤버 변수로 함께 저장)
3) 길이를 저장하는 변수를 생성하여 이를 활용한다. (Queue size를 묶어 같은 레벨끼리 처리)
중요 파트!