인접이란, 두 정점을 연결하는 간선이 있는 것을 말한다.
👉 간선의 수가 많고, 정점간 연결여부를 빠르게 파악해야할 때 적합
//directed, unweighted graph
//여기서 배열의 인덱스를 정점으로 사용한다.
class GraphiWithAdjacencyMatrix {
constructor() {
this.matrix = [];
}
addVertex() {
const currentLength = this.matrix.length;
for(let i=0; i<currentLength; i++) {
this.matrix[i].push(0);
}
this.matrix.push(new Array(currentLength+1).fill(0));
}
contains(vertex) {
if(vertex<this.matrix.length) {
return true;
}
return false;
}
addEdge(from, to) {
const currentLength = this.matrix.length; //정점의 개수 (최소 정점 값은 0)
if(from === undefined || to === undefined) return;
if(from > currentLength-1 || to > currentLength-1 || from < 0 || to < 0) return;
this.matrix[from][to] = 1;
}
hasEdge(from, to) {
return !!this.matrix[from][to];
//matrix[from][to]는 0, 1, undefined가 나올 수 있는데, true, false로만 리턴하기 위해서는 !!를 작성해주면 된다.
}
removeEdge(from, to) {
const currentLength = this.matrix.length;
if(from === undefined || to === undefined) return;
if(from > currentLength-1 || to > currentLength-1 || from < 0 || to < 0) return;
this.matrix[from][to] = 0;
}
👉 간선의 수가 적고, 메모리를 효율적으로 사용해야하는 경우 적합
class GraphWithAdjacencyList {
//undirected graph
constructor() {
this.vertices = {};
}
addVertex(vertex) {
this.vertices[vertex] = this.vertices[vertex] || [];
}
contains(vertex) {
return !!this.vertices[vertex];
}
addEdge(fromVertex, toVertex) {
if(!this.contains(fromVertex) || !this.contains(toVertex)) return;
if(!this.hasEdge(fromVertex, toVertex)) {
this.vertices[fromVertex].push(toVertex);
}
if(!this.hasEdge(toVertex, fromVertex)) {
this.vertices[toVertex].push(fromVertex);
}
}
hasEdge(fromVertex, toVertex) {
if(!this.contains(fromVertex)) {
return false
}
return this.vertices[fromVertex].includes(toVertex);
}
removeEdge(fromVertex, toVertex) {
if(!this.contains(fromVertex) || !this.contains(toVertex)) return;
if(this.hasEdge(fromVertex, toVertex)) {
const toVertexIndex = this.vertices[fromVertex].indexOf(toVertex);
this.vertices[fromVertex].splice(toVertexIndex,1);
//무방향 그래프이므로, 정점 A의 리스트에 B가 있다면, 정점 B의 리스트에도 A가 있으므로 indexOf의 값이 -1이 나올 수 없다.
}
if(this.hasEdge(toVertex, fromVertex)) {
const fromVertexIndex = this.vertices[toVertex].indexOf(fromVertex);
this.vertices[toVertex].splice(fromVertexIndex,1);
}
return;
}
removeVertex(vertex) {
if(this.contains(vertex)) {
while(this.vertices[vertex].length > 0) {
this.removeEdge(this.vertices[vertex][0], vertex);
}
delete this.vertices[vertex];
}
}
노드의 자식노드들을 우선으로 더이상 자식 노드가 없을때까지 탐색한다. stack 또는 재귀를 활용해 구현한다. 시간복잡도는 O(V+E)를 갖는다.
노드의 같은 레벨의 노드들(형제노드)을 우선으로 같은 레벨의 노드가 없을때까지 탐색한다. 큐를 활용해 구현한다. 시간복잡도는 O(V+E)를 갖는다.
reference