트리나 그래프 등에서 하나의 노드를 최대한 깊게 들어가면서 해를 찾는 탐색 기법

인접한 후보 노드만 기억하면 되므로 적은 기억공간 소요
노트가 깊은 단계에 있을 경우 빠르게 정답 산출
선택한 경로가 답이 아닐 경우 불필요한 탐색 가능
최단 경로 구할 시 찾은 해가 정답이 아닐 경우 발생 ⇒ BFS
Graph.dfsRecursiveVisit()function Graph() {
this.edge = {};
this.visited = {};
}
// addVertex() : 정점(vertex) 추가
Graph.prototype.addVertex = function (v) {
this.edge[v] = [];
this.visited[v] = false;
};
// addEdge() : 간선(edge) 추가
Graph.prototype.addEdge = function (v1, v2) {
this.edge[v1].push(v2); // v1 -> v2
};
// print() : 현재 Graph에 연결 상태 출력
Graph.prototype.print = function () {
for (let vertex in this.edge) {
let neighbors = this.edge[vertex];
if (neighbors.length === 0) continue;
process.stdout.write(`${vertex} -> `);
for (let j = 0; j < neighbors.length; j++) {
process.stdout.write(`${neighbors[j]} `);
}
console.log("");
}
};
//dfs() : DFS 탐색
Graph.prototype.dfs = function (startVertex) {
this._dfsRecursiveVisit(startVertex);
};
//_dfsRecursiveVisit() : 재귀를 이용한 DFS 탐색
Graph.prototype._dfsRecursiveVisit = function (vertex) {
// 1. 종료 조건
if (this.visited[vertex]) {
return;
}
// 2. 재귀 호출을 하면서 수행해야할 코드
this.visited[vertex] = true;
console.log(`visit "${vertex}"`);
let neighbors = this.edge[vertex];
for (let i = 0; i < neighbors.length; i++) {
this._dfsRecursiveVisit(neighbors[i]);
}
};
let graph = new Graph();
let vertices = ["A", "B", "C", "D", "E", "F", "G", "H", "I"];
for (let i = 0; i < vertices.length; i++) {
graph.addVertex(vertices[i]);
}
graph.addEdge("A", "B");
graph.addEdge("A", "C");
graph.addEdge("A", "D");
graph.addEdge("C", "G");
graph.addEdge("D", "G");
graph.addEdge("D", "H");
graph.addEdge("B", "E");
graph.addEdge("B", "F");
graph.addEdge("E", "I");
graph.print();
console.log("");
graph.dfs("A");
------------------------------------------------------------------------
OUTPUT
A -> B C D
B -> E F
C -> G
D -> G H
E -> I
visit "A"
visit "B"
visit "E"
visit "I"
visit "F"
visit "C"
visit "G"
visit "D"
visit "H"
Graph.dfsLoopVisit()import { Stack } from "./stack3.mjs";
function Graph() {
this.edge = {};
this.visited = {};
}
// addVertex() : 정점(vertex) 추가
Graph.prototype.addVertex = function (v) {
this.edge[v] = [];
this.visited[v] = false;
};
// addEdge() : 간선(edge) 추가
Graph.prototype.addEdge = function (v1, v2) {
this.edge[v1].push(v2); // v1 -> v2
};
// print() : 현재 Graph에 연결 상태 출력
Graph.prototype.print = function () {
for (let vertex in this.edge) {
let neighbors = this.edge[vertex];
if (neighbors.length === 0) continue;
process.stdout.write(`${vertex} -> `);
for (let j = 0; j < neighbors.length; j++) {
process.stdout.write(`${neighbors[j]} `);
}
console.log("");
}
};
//dfs() : DFS 탐색
Graph.prototype.dfs = function (startVertex) {
this._dfsLoopVisit(startVertex);
};
//_dfsLoopVisit() : 스택를 이용한 DFS 탐색
Graph.prototype._dfsLoopVisit = function (vertex) {
let stack = new Stack();
stack.push(vertex);
// 스택이 빌때까지 반복
while (!stack.isEmpty()) {
let vertex = stack.pop();
// 방문했는지 확인
if (this.visited[vertex]) {
continue;
}
this.visited[vertex] = true;
console.log(`visit "${vertex}"`);
let neighbors = this.edge[vertex];
for (let i = neighbors.length - 1; i >= 0; i--) {
stack.push(neighbors[i]);
}
}
};
let graph = new Graph();
let vertices = ["A", "B", "C", "D", "E", "F", "G", "H", "I"];
for (let i = 0; i < vertices.length; i++) {
graph.addVertex(vertices[i]);
}
graph.addEdge("A", "B");
graph.addEdge("A", "C");
graph.addEdge("A", "D");
graph.addEdge("C", "G");
graph.addEdge("D", "G");
graph.addEdge("D", "H");
graph.addEdge("B", "E");
graph.addEdge("B", "F");
graph.addEdge("E", "I");
graph.print();
console.log("");
graph.dfs("A");
------------------------------------------------------------------------
OUTPUT
A -> B C D
B -> E F
C -> G
D -> G H
E -> I
visit "A"
visit "B"
visit "E"
visit "I"
visit "F"
visit "C"
visit "G"
visit "D"
visit "H"
트리나 그래프 등에서 인접한 노드를 우선 방문하면서 넓게 움직이며 해를 찾는 탐색 기법

Graph.bfs() , Graph._bfsLoopVisit()import { Queue } from "./queue3.mjs";
function Graph() {
this.edge = {};
this.visited = {};
}
// addVertex() : 정점(vertex) 추가
Graph.prototype.addVertex = function (v) {
this.edge[v] = [];
this.visited[v] = false;
};
// addEdge() : 간선(edge) 추가
Graph.prototype.addEdge = function (v1, v2) {
this.edge[v1].push(v2); // v1 -> v2
};
// print() : 현재 Graph에 연결 상태 출력
Graph.prototype.print = function () {
for (let vertex in this.edge) {
let neighbors = this.edge[vertex];
if (neighbors.length === 0) continue;
process.stdout.write(`${vertex} -> `);
for (let j = 0; j < neighbors.length; j++) {
process.stdout.write(`${neighbors[j]} `);
}
console.log("");
}
};
// bfs() : BFS 탐색
Graph.prototype.bfs = function (startVertex) {
this._bfsLoopVisit(startVertex);
};
// _bfsLoopVisit() : 큐를 이용한 BFS 탐색
Graph.prototype._bfsLoopVisit = function (vertex) {
let queue = new Queue();
queue.enqueue(vertex);
while (!queue.isEmpty()) {
let vertex = queue.dequeue();
if (this.visited[vertex]) {
continue;
}
this.visited[vertex] = true;
console.log(`visit "${vertex}"`);
let neighbors = this.edge[vertex];
for (let i = 0; i < neighbors.length; i++) {
queue.enqueue(neighbors[i]);
}
}
};
let graph = new Graph();
let vertices = ["A", "B", "C", "D", "E", "F", "G", "H", "I"];
for (let i = 0; i < vertices.length; i++) {
graph.addVertex(vertices[i]);
}
graph.addEdge("A", "B");
graph.addEdge("A", "C");
graph.addEdge("A", "D");
graph.addEdge("C", "G");
graph.addEdge("D", "G");
graph.addEdge("D", "H");
graph.addEdge("B", "E");
graph.addEdge("B", "F");
graph.addEdge("E", "I");
graph.print();
console.log("");
graph.bfs("A");
------------------------------------------------------------------------
OUTPUT
A -> B C D
B -> E F
C -> G
D -> G H
E -> I
visit "A"
visit "B"
visit "C"
visit "D"
visit "E"
visit "F"
visit "G"
visit "H"
visit "I"
Graph.shortestPath() , Graph._bfsShortestPath() , Graph._from_to_path()import { Queue } from "./queue3.mjs";
import { Stack } from "./stack3.mjs";
function Graph() {
this.edge = {};
this.visited = {};
}
// addVertex() : 정점(vertex) 추가
Graph.prototype.addVertex = function (v) {
this.edge[v] = [];
this.visited[v] = false;
};
// addEdge() : 간선(edge) 추가
Graph.prototype.addEdge = function (v1, v2) {
this.edge[v1].push(v2); // v1 -> v2
};
// print() : 현재 Graph에 연결 상태 출력
Graph.prototype.print = function () {
for (let vertex in this.edge) {
let neighbors = this.edge[vertex];
if (neighbors.length === 0) continue;
process.stdout.write(`${vertex} -> `);
for (let j = 0; j < neighbors.length; j++) {
process.stdout.write(`${neighbors[j]} `);
}
console.log("");
}
};
// bfs() : BFS 탐색
Graph.prototype.bfs = function (startVertex) {
this._bfsLoopVisit(startVertex);
};
// _bfsLoopVisit() : 큐를 이용한 BFS 탐색
Graph.prototype._bfsLoopVisit = function (vertex) {
let queue = new Queue();
queue.enqueue(vertex);
while (!queue.isEmpty()) {
let vertex = queue.dequeue();
if (this.visited[vertex]) {
continue;
}
this.visited[vertex] = true;
console.log(`visit "${vertex}"`);
let neighbors = this.edge[vertex];
for (let i = 0; i < neighbors.length; i++) {
queue.enqueue(neighbors[i]);
}
}
};
// _bfsShortestPath() : 다른 정점 간 최단 경로 비용 산출
Graph.prototype._bfsShortestPath = function (vertex) {
let queue = new Queue();
queue.enqueue(vertex);
let distance = {};
let pre_visit = {};
for (let vertex in this.edge) {
distance[vertex] = 0;
pre_visit[vertex] = null;
}
while (!queue.isEmpty()) {
let vertex = queue.dequeue();
this.visited[vertex] = true;
console.log(`visit "${vertex}"`);
let neighbors = this.edge[vertex];
for (let i = 0; i < neighbors.length; i++) {
if (!this.visited[neighbors[i]]) {
distance[neighbors[i]] = distance[vertex] + 1;
pre_visit[neighbors[i]] = vertex;
queue.enqueue(neighbors[i]);
}
}
}
return { distance, pre_visit };
};
// _from_to_path() : from 정점에서 to 정점으로 최단 경로 출력
Graph.prototype._from_to_path = function (pre_visit, from, to) {
let stack = new Stack();
for (let v = to; v !== from; v = pre_visit[v]) {
stack.push(v);
}
stack.push(from);
while (!stack.isEmpty()) {
let v = stack.pop();
process.stdout.write(`${v} => `);
}
console.log("end");
};
// shortestPath() : 다른 정점 간 최단 경로 탐색
Graph.prototype.shortestPath = function (startVertex) {
let result = this._bfsShortestPath(startVertex);
console.log(result.distance);
console.log(result.pre_visit);
for (let vertex in this.edge) {
if (vertex === startVertex) continue;
this._from_to_path(result.pre_visit, startVertex, vertex);
}
};
let graph = new Graph();
let vertices = ["A", "B", "C", "D", "E", "F", "G", "H", "I"];
for (let i = 0; i < vertices.length; i++) {
graph.addVertex(vertices[i]);
}
graph.addEdge("A", "B");
graph.addEdge("A", "C");
graph.addEdge("A", "D");
graph.addEdge("C", "G");
graph.addEdge("D", "G");
graph.addEdge("D", "H");
graph.addEdge("B", "E");
graph.addEdge("B", "F");
graph.addEdge("E", "I");
graph.print();
console.log("");
graph.shortestPath("A");
------------------------------------------------------------------------
OUTPUT
A -> B C D
B -> E F
C -> G
D -> G H
E -> I
visit "A"
visit "B"
visit "C"
visit "D"
visit "E"
visit "F"
visit "G"
visit "G"
visit "H"
visit "I"
{ A: 0, B: 1, C: 1, D: 1, E: 2, F: 2, G: 2, H: 2, I: 3 }
{
A: null,
B: 'A',
C: 'A',
D: 'A',
E: 'B',
F: 'B',
G: 'D',
H: 'D',
I: 'E'
}
A => B => end
A => C => end
A => D => end
A => B => E => end
A => B => F => end
A => D => G => end
A => D => H => end
A => B => E => I => end