DFS는 깊이 우선 탐색으로, 한 노드에서 다음 분기로 넘어가기 전에 해당 분기를 완벽하게 탐색하는 방식을 말합니다. 스택 혹은 재귀 함수를 사용해서 구현할 수 있습니다.
BFS는 너비 우선 탐색으로, 특정 노드에서 탐색을 시작하여 같은 레벨에 있는 모든 노드를 탐색한 후 다음 하위 레벨로 내려가 탐색을 진행하는 방식입니다. 큐를 이용하여 구현할 수 있습니다.
- 최선의 경우, 가장 빠른 알고리즘이다. “운 좋게” 해에 도달하는 올바른 경로를 선택한다면, 최소 실행시간에 해를 찾는다.
- BFS에 비해 저장공간의 필요성이 적다. 백트래킹을 해야하는 노드들만 저장해주면 된다.
- 찾은 해가 최적이 아닐 가능성이 있다.
- 최악의 경우, 가능한 모든 경로를 탐험하고나서야 해를 찾으므로, 해에 도달하는 데 가장 오래 시간 소모
- 너비를 우선으로 탐색하기 때문에 답이 되는 경로가 여러 개인 경우에도 최단 경로를 보장
- 최소 실행시간보다는 오래 걸릴다는 것이 거의 확실
- 최악의 경우, 실행에 가장 긴 시간이 걸릴 수 있다.
// Using Recursive Function
void DFS(int node) {
visited[node] = true;
System.out.print(node + " -> ");
for(int childNode : graph[node]) {
if(!visited[childNode]) {
DFS(childNode);
}
}
}
// Using Stack
void DFS(int start) {
Stack<Integer> stack = new Stack<>();
stack.add(start);
System.out.print(start + " -> ");
visited[start] = true;
while(!stack.isEmpty()) {
int curNode = stack.peek();
boolean hasNearNode = false;
for(int nearNode : graph[curNode]) {
if(!visited[nearNode]) {
visited[nearNode] = true;
System.out.print(nearNode + " -> ");
hasNearNode = true;
stack.add(nearNode);
break;
}
}
if(!hasNearNode) stack.pop();
}
}
// Using Queue
void BFS(int start) {
Queue<Integer> q = new LinkedList<>();
q.add(start);
visitied[start] = true;
while (!q.isEmpty()) {
int curNode = q.poll();
System.out.print(curNode + " -> ");
for(int adjNode : graph[curNode]) {
if(!visitied[adjNode]) {
q.add(adjNode);
visitied[adjNode] = true;
}
}
}
}
DFS와 BFS는 인접행렬로 구현하는냐, 인접리스트로 구현하는냐에 따라 시간 복잡도가 다르게 나옵니다.