DFS
, BFS
란?DFS
: 깊이 우선 탐색 - 정점의 자식을 우선적으로 탐색 [스택 이용]BFS
: 너비 우선 탐색 - 정점과 같은 레벨에 있는 노드를 우선적으로 탐색 [큐 이용]DFS
- Depth First Search
[깊이 우선 탐색]
- 시작 노드를 스택에 삽입하고 방문 표시
- 스택이 비어있지 않으면 노드를 하나 꺼냄
- 꺼낸 노드의 인접 노드를 스택에 넣고 방문표시
* 같은 DFS
이지만 방식에 따라 방문 방향이 다를 수 있음에 주의하자.
DFS
- 재귀호출JAVA
graph
, visited
는 public static
필드로 두었다.
Collection Framework
의 HashMap
과 ArrayList
를 사용했다.
public void dfsRecursive(String startNode) {
visited.add(startNode);
for (String node : graph.get(startNode)) {
if (!visited.contains(node)) {
dfsRecursive(node);
}
}
}
C++
graph
, visited
는 public
필드로 두었다.
C++ STL
의 map
과 vector
를 사용했다.
void dfsRecursive(const string& startNode) {
visited.push_back(startNode);
for (const string& node : graph[startNode]) {
if (find(visited.begin(), visited.end(), node) == visited.end()) {
dfsRecursive(node);
}
}
}
python
클래스를 만들어 graph
, visited
를 필드로 두었다.
graph
는 dict() key: str => value: list()
, visited
는 list()
이다.
def dfs_recursive(self, start_node: str):
self.visited.append(start_node)
for node in self.graph[start_node]:
if node not in self.visited:
self.dfs_recursive(node)
DFS
- 반복문JAVA
public void dfsLoop(String startNode) {
ArrayList<String> needVisit = new ArrayList<>();
needVisit.add(startNode);
while (!needVisit.isEmpty()) { // 스택이 빌 때까지 진행
// 끝에서부터 꺼내온다 => 스택
String node = needVisit.remove(needVisit.size() - 1);
// 방문하지 않은 노드라면 방문 표시 후 스택에 넣는다.
if (!visited.contains(node)) {
visited.add(node);
needVisit.addAll(graph.get(node));
}
}
}
C++
void dfsLoop(const string& startNode) {
stack<string> needVisit;
needVisit.push(startNode);
while (!needVisit.empty()) {
string node = needVisit.top(); needVisit.pop();
if (find(visited.begin(), visited.end(), node) == visited.end()) {
visited.push_back(node);
for (const string& child : graph[node])
needVisit.push(child);
}
}
}
python
def dfs_loop(self, start_node: str):
need_visit = list()
need_visit.append(start_node)
# 빈 sequence(string, tuple, list)는 false 값을 가진다.
while need_visit:
node = need_visit.pop()
if node not in self.visited:
self.visited.append(node)
need_visit.extend(self.graph[node])
BFS
- Breadth First Search
[너비 우선 탐색]
- 시작 노드를 큐에 삽입하고 방문 표시
- 큐가 비어있지 않으면 노드를 하나 꺼냄
- 꺼낸 노드의 인접 노드를 큐에 넣고 방문표시
* 같은 BFS
이지만 방식에 따라 방문 방향이 다를 수 있음에 주의하자.
* BFS
는 재귀호출과 반복문의 차이가 거의 없다.
BFS
- 재귀호출JAVA
public void bfsRecursive() {
if (queue.isEmpty()) return;
String node = queue.poll();
for (String nextNode : graph.get(node)) {
if (!visited.contains(nextNode)) {
visited.add(nextNode);
queue.add(nextNode);
}
}
bfsRecursive();
}
C++
void bfsRecursive() {
if (q.empty()) return;
const auto& startNode = q.front(); q.pop();
for (const string& node : graph[startNode]) {
if (find(visited.begin(), visited.end(), node) == visited.end()) {
visited.push_back(node);
q.push(node);
}
}
bfsRecursive();
}
python
def bfs_recursive(self):
if self.queue.empty():
return
start_node = self.queue.get()
for node in self.graph[start_node]:
if node not in self.visited:
self.visited.append(node)
self.queue.put(node)
self.bfs_recursive()
BFS
- 반복문JAVA
public void bfsLoop(String startNode) {
queue.add(startNode);
while (!queue.isEmpty()) {
// 앞에서부터 꺼내온다 => 큐
String node = queue.poll();
for (String nextNode : graph.get(node)) {
if (!visited.contains(nextNode)) {
visited.add(nextNode);
queue.add(nextNode);
}
}
}
}
C++
void bfsLoop(const string& startNode) {
queue<string> needVisit;
needVisit.push(startNode);
while (!needVisit.empty()) {
string node = needVisit.front(); needVisit.pop();
if (find(visited.begin(), visited.end(), node) == visited.end()) {
visited.push_back(node);
for (const string& child : graph[node])
needVisit.push(child);
}
}
}
python
def bfs_loop(self, start_node: str):
self.queue.appendleft(start_node)
while self.queue: # 빈 sequence(string, tuple, list)는 false 값을 가진다
node = self.queue.pop()
if node not in self.visited:
self.visited.append(node)
self.queue.extendleft(self.graph[node])