정점과 간선으로 구성되어 네트워크 구조를 추상화한 비선형 자료 구조
그래프 특징
그래프 종류
그래프 종류 2
그래프 표현 방법
그래프 구현
/* 방향 그래프 */
// Graph(): edge object 객체 저장을 위한 생성자
// key : vertex
// value : list 형태로 연결된 vertex를 표현하여 edge 연결 관계 표현
function Graph() {
this.edge = {};
}
// addVertex() : 정점(vertex) 추가
Graph.prototype.addVertex = function (v) {
this.edge[v] = [];
};
// addEdge() : 간선(edge) 추가
Graph.prototype.addEdge = function (v1, v2) {
this.edge[v1].push(v2);
};
// removeEdge(): 간선(edge) 삭제
Graph.prototype.removeEdge = function (v1, v2) {
if (this.edge[v1]) {
let idx = this.edge[v1].indexOf(v2);
if (idx != -1) {
this.edge[v1].splice(idx, 1);
}
if (this.edge[v1].length === 0) {
delete this.edge[v1];
}
}
};
// removeVertex(): 정점(vertex) 삭제
Graph.prototype.removeVertex = function (v) {
if (this.edge[v] === undefined) return;
let length = this.edge[v].length; // changed length
let connectedVertex = [...this.edge[v]]; // object copy
for (let i = 0; i < length; i++) {
this.removeEdge(v, connectedVertex[i]);
}
}:
// sizeVertex(): vertex 개수 반환
Graph.prototype.sizeVertex = function () {
return Object.keys(this.edge).length;
};
// sizeEdge() : edge 개수 반환
Graph.prototype.sizeEdge = function (vertex) {
return this.edge[vertex] ? Object.keys(this.edge[vertex]).length : 0;
};
// 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("");
}
};
/* 무방향 그래프 */
// addEdge() : 간선(edge) 추가
Graph.prototype.addEdge = function (v1, v2) {
this.edge[v1].push(v2);
this.edge[v2].push(v1);
};
// removeEdge() : 간선(edge) 삭제
Graph.prototype.removeEdge = function (v1, v2) {
if (this.edge[v2]) {
let idx = this.edge[v2].indexOf(v1);
if (idx != -1) {
this.edge[v2].splice(idx, 1);
}
if (this.edge[v2].length === 0) {
delete this.edge[v2];
}
}
};
// dfs() : DFS 탐색
Graph.prototype.dfs = function (startVertex) {
this._dfsRecursiveVisit(startVertex);
};
// _dfsRecursiveVisit() : 재귀를 이용한 DFS 탐색
Graph.prototype._dfsRecursiveVisit = function (vertex) {
if (this.visited[vertex]) {
return;
}
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]);
}
};
// 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]);
}
}
};
// 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();
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++) {
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);
}
};