forked from TheAlgorithms/JavaScript
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
merge: Add Graph3 (add DFS in Iterative Way) (TheAlgorithms#944)
* Add Graph3 (add DFS in Iterative Way) * Remove example code and add test code (Graph3) * Remove redundant code (like return undefined)
- Loading branch information
Showing
2 changed files
with
183 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
class Graph { | ||
constructor () { | ||
this.adjacencyObject = {} | ||
} | ||
|
||
addVertex (vertex) { | ||
if (!this.adjacencyObject[vertex]) this.adjacencyObject[vertex] = [] | ||
} | ||
|
||
addEdge (vertex1, vertex2) { | ||
this.adjacencyObject[vertex1].push(vertex2) | ||
this.adjacencyObject[vertex2].push(vertex1) | ||
} | ||
|
||
removeEdge (vertex1, vertex2) { | ||
this.adjacencyObject[vertex1] = this.adjacencyObject[vertex1].filter( | ||
(v) => v !== vertex2 | ||
) | ||
this.adjacencyObject[vertex2] = this.adjacencyObject[vertex2].filter( | ||
(v) => v !== vertex1 | ||
) | ||
} | ||
|
||
removeVertex (vertex) { | ||
while (this.adjacencyObject[vertex].length) { | ||
const adjacentVertex = this.adjacencyObject[vertex].pop() | ||
this.removeEdge(vertex, adjacentVertex) | ||
} | ||
} | ||
|
||
/** | ||
* Return DFS (Depth First Search) List Using Recursive Method | ||
*/ | ||
DFS (start) { | ||
if (!start) return null | ||
|
||
const result = [] | ||
const visited = {} | ||
const adjacencyObject = this.adjacencyObject | ||
|
||
function dfs (vertex) { | ||
if (!vertex) return null | ||
visited[vertex] = true | ||
result.push(vertex) | ||
adjacencyObject[vertex].forEach((neighbor) => { | ||
if (!visited[neighbor]) { | ||
dfs(neighbor) | ||
} | ||
}) | ||
} | ||
|
||
dfs(start) | ||
return result | ||
} | ||
|
||
/** | ||
* Return DFS(Depth First Search) List Using Iteration | ||
*/ | ||
DFSIterative (start) { | ||
if (!start) return null | ||
|
||
const stack = [start] | ||
const visited = {} | ||
visited[start] = true | ||
|
||
const result = [] | ||
let currentVertex | ||
|
||
while (stack.length) { | ||
currentVertex = stack.pop() | ||
result.push(currentVertex) | ||
|
||
this.adjacencyObject[currentVertex].forEach((neighbor) => { | ||
if (!visited[neighbor]) { | ||
visited[neighbor] = true | ||
stack.push(neighbor) | ||
} | ||
}) | ||
} | ||
return result | ||
} | ||
|
||
BFS (start) { | ||
if (!start) return null | ||
|
||
const queue = [start] | ||
const visited = {} | ||
visited[start] = true | ||
|
||
let currentVertex | ||
const result = [] | ||
|
||
while (queue.length) { | ||
currentVertex = queue.shift() | ||
result.push(currentVertex) | ||
|
||
this.adjacencyObject[currentVertex].forEach((neighbor) => { | ||
if (!visited[neighbor]) { | ||
visited[neighbor] = true | ||
queue.push(neighbor) | ||
} | ||
}) | ||
} | ||
return result | ||
} | ||
} | ||
|
||
export { Graph } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
import { Graph } from '../Graph3' | ||
|
||
describe('Test Graph3', () => { | ||
const g = new Graph() | ||
|
||
// Add Vertices | ||
g.addVertex('A') | ||
g.addVertex('B') | ||
g.addVertex('C') | ||
g.addVertex('D') | ||
g.addVertex('E') | ||
g.addVertex('F') | ||
|
||
// Add Edges | ||
g.addEdge('A', 'B') | ||
g.addEdge('A', 'C') | ||
g.addEdge('B', 'D') | ||
g.addEdge('C', 'E') | ||
g.addEdge('D', 'E') | ||
g.addEdge('D', 'F') | ||
g.addEdge('E', 'F') | ||
|
||
/** | ||
* A - B - D | ||
* | / \ | ||
* C - - E - F | ||
* | ||
* DFS(Iterative): A-C-E-F-D-B | ||
* DFS(Recursive): A-B-D-E-C-F | ||
* BFS: A-B-C-D-E-F | ||
*/ | ||
it('Check iterative DFS List', () => { | ||
const iterativeDFSList = g.DFSIterative('A') | ||
expect(iterativeDFSList).toEqual(['A', 'C', 'E', 'F', 'D', 'B']) | ||
}) | ||
|
||
it('Check recursive DFS List', () => { | ||
const recursiveDFSList = g.DFS('A') | ||
expect(recursiveDFSList).toEqual(['A', 'B', 'D', 'E', 'C', 'F']) | ||
}) | ||
|
||
it('Check BFS List', () => { | ||
const BFSList = g.BFS('A') | ||
expect(BFSList).toEqual(['A', 'B', 'C', 'D', 'E', 'F']) | ||
}) | ||
|
||
/** | ||
* Test After Remove 'B' Vertex | ||
* A D | ||
* | / \ | ||
* C - - E - F | ||
* | ||
* DFS(Iterative): A-C-E-F-D | ||
* DFS(Recursive): A-C-E-D-F | ||
* BFS: A-C-E-D-F | ||
*/ | ||
|
||
it('Check iterative DFS List After Removing Vertex B', () => { | ||
g.removeVertex('B') | ||
const iterativeDFSList = g.DFSIterative('A') | ||
expect(iterativeDFSList).toEqual(['A', 'C', 'E', 'F', 'D']) | ||
}) | ||
|
||
it('Check recursive DFS List After Removing Vertex B', () => { | ||
g.removeVertex('B') | ||
const recursiveDFSList = g.DFS('A') | ||
expect(recursiveDFSList).toEqual(['A', 'C', 'E', 'D', 'F']) | ||
}) | ||
|
||
it('Check BFS List After Removing Vertex B', () => { | ||
g.removeVertex('B') | ||
const BFSList = g.BFS('A') | ||
expect(BFSList).toEqual(['A', 'C', 'E', 'D', 'F']) | ||
}) | ||
}) |