탐색 알고리즘 DFS/BFS
2021. 1. 24. 13:57
반응형
DFS (Depth-First-Search)
- 깊이 우선 탐색 - 그래프에서 깊은 부분을 우선적으로 탐색하는 알고리즘
- 그래프는 노드와 간선으로 표현되며 노드는 index로 표현하고 간선은 distance로 표현
- 스택 자료구조를 이용
BFS(Breath-First-Search)
- 너비 우선 탐색 - 그래프에서 가장 가까운 노드부터 우선적으로 탐색하는 알고리즘
- 큐 자료구조를 이용
그래프는 다음 2가지 방식으로 표현 가능하다.
- 인접 행렬 : 2차원 배열로 그래프의 관계를 표현
- 인접 리스트 : 리스트로 그래프의 관계를 표현
인접 행렬 방식
public static final int INF = (int)1e9;
public static int[][] graph = new int[][]{
{0,5,3},
{5,0,INF},
{3,INF,0}
};
- INF로 표현된 요소는 둘 사이가 연결되어있지 않다는 뜻이다.
- 노드0은 노드1과 거리5만큼 떨어져 연결되어있다.
- 노드1과 노드2는 연결되어있지 않다.
- 노드0과 노드2는 거리3만큼 떨어져 연결되어있다.
인접 리스트 방식
public class Main {
public static ArrayList<ArrayList<Node>> graph = new ArrayList<ArrayList<Node>>();
public static void main(String[] args) {
for(int i = 0; i < 3; i++){
graph.add(new ArrayList<>());
}
graph.get(0).add(new Node(1,5));
graph.get(0).add(new Node(2,3));
graph.get(1).add(new Node(0,5));
graph.get(2).add(new Node(0,3));
}
}
- 연결되어있지 않은 노드는 INF로 표현하지 않아도 된다.
- 위 인접 행렬과 같은 노드와 거리로 표현된다.
인접 행렬, 인접 리스트 방식의 차이점
- 인접행렬은 연결되어있지 않은 노드도 INF로 표현을 한다.
- 인접 리스트는 연결되어있지 않으면 표현 자체를 하지 않는다.
- 따라서 인접 리스트는 연결된 정보만을 표현하기 때문에 메모리를 인접행렬 방식보다 효율적으로 사용한다.
- 하지만 인접 리스트 방식은 특정 두 노드가 연결되어 있는지에 대한 정보를 얻는 속도가 느리다.
DFS 동작 원리
- 탐색 시작 노드를 스택에 삽입하고 방문처리를 한다.
- 스택의 최상단 노드에 방문하지 않은 연결되어있는 인접 노드가 있으면 스택에 넣고 방문처리를 한다.
- 1,2번 과정을 반복한다.
public class Main {
public static boolean[] visited = new boolean[100001];
public static ArrayList<ArrayList<Integer>> graph = new ArrayList<ArrayList<Integer>>();
public static void Dfs(int now){
//스택에 시작노드를 넣고 방문처리
visited[now] = true;
System.out.println(" " + now);
//시작노드와 연결된 노드부터 탐색
for(int i = 0; i < graph.get(now).size(); i++){
//인접 노드 중 방문하지 않은 노드가 있다면
if(!visited[graph.get(now).get(i)]){
Dfs(graph.get(now).get(i));
}
}
}
public static void main(String[] args) {
//그래프 초기화
for(int i = 0; i <= 9; i++){
graph.add(new ArrayList<>());
}
//그래프 채워넣기
graph.get(1).add(2);
graph.get(1).add(3);
graph.get(1).add(8);
graph.get(2).add(1);
graph.get(2).add(7);
graph.get(3).add(1);
graph.get(3).add(4);
graph.get(3).add(5);
graph.get(4).add(3);
graph.get(4).add(5);
graph.get(5).add(3);
graph.get(5).add(4);
graph.get(6).add(7);
graph.get(7).add(2);
graph.get(7).add(6);
graph.get(7).add(8);
graph.get(8).add(1);
graph.get(8).add(7);
Dfs(1);
}
}
BFS 동작 원리
- 탐색 시작 노드를 큐에 삽입하고 방문처리
- 큐에서 노드를 꺼내 해당 노드에 인접하는 노드중 방문하지 않은 노드를 다 큐에 삽입하고 방문처리
- 2번 과정을 반복한다.
public class Main {
public static boolean[] visited = new boolean[100001];
public static ArrayList<ArrayList<Integer>> graph = new ArrayList<ArrayList<Integer>>();
public static void Bfs(int now){
Queue<Integer> queue = new LinkedList<>();
//큐에 시작노드를 넣고 방문처리
queue.offer(now);
visited[now] = true;
//큐가 빌때 까지 반복
while(!queue.isEmpty()){
//큐에서 노드를 꺼낸다.
int node = queue.poll();
System.out.print(" " + node);
//인접한 노드중 방문하지 않은 노드 큐에 삽입
for(int i = 0; i < graph.get(node).size(); i++){
if(!visited[graph.get(node).get(i)]){
queue.offer(graph.get(node).get(i));
visited[graph.get(node).get(i)] = true;
}
}
}
}
public static void main(String[] args) {
//그래프 초기화
for(int i = 0; i <= 9; i++){
graph.add(new ArrayList<>());
}
//그래프 채워넣기
graph.get(1).add(2);
graph.get(1).add(3);
graph.get(1).add(8);
graph.get(2).add(1);
graph.get(2).add(7);
graph.get(3).add(1);
graph.get(3).add(4);
graph.get(3).add(5);
graph.get(4).add(3);
graph.get(4).add(5);
graph.get(5).add(3);
graph.get(5).add(4);
graph.get(6).add(7);
graph.get(7).add(2);
graph.get(7).add(6);
graph.get(7).add(8);
graph.get(8).add(1);
graph.get(8).add(7);
Bfs(1);
}
}
반응형
'자료구조와 알고리즘 > 알고리즘' 카테고리의 다른 글
신장 트리와 크루스칼 알고리즘 (0) | 2022.02.06 |
---|---|
서로소 집합 알고리즘 (0) | 2022.02.06 |
이진 탐색 (0) | 2021.02.02 |
정렬 알고리즘 (0) | 2021.01.29 |