Skip to content

Commit 829552e

Browse files
committed
[Graphs]
1 parent fc26932 commit 829552e

18 files changed

+426
-25
lines changed

.eslintrc.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
"no-restricted-globals": 0,
3131
"no-multi-assign": 0,
3232
"prefer-destructuring": ["error", {"object": true, "array": false}],
33-
"padded-blocks": 0
33+
"padded-blocks": 0,
34+
"no-sparse-arrays": 0,
35+
"array-bracket-spacing": 0
3436
}
3537
}

examples/chapter12/04-Dijkstra.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ const graph = [
1111

1212
console.log("********* Dijkstra's Algorithm - Shortest Path ***********");
1313

14-
var dist = dijkstra(graph, 0);
14+
const dist = dijkstra(graph, 0);
1515

1616
for (i = 0; i < dist.length; i++){
1717
console.log(i + '\t\t' + dist[i]);

src/ts/algorithms/graph/breadth-first-search.ts

+6-5
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,17 @@ const initializeColor = (vertices: (string | number)[]) => {
1515
return color;
1616
};
1717

18-
export const breadthFirstSearch = (graph: Graph, callback: Function) => {
18+
export const breadthFirstSearch = (graph: Graph, startVertex: any, callback: Function) => {
1919
const vertices = graph.getVertices();
2020
const adjList = graph.getAdjList();
2121
const color = initializeColor(vertices);
2222
const queue = new Queue();
23-
queue.enqueue(vertices);
23+
24+
queue.enqueue(startVertex);
2425

2526
while (!queue.isEmpty()) {
26-
const u = queue.dequeue(),
27-
neighbors = adjList.get(u);
27+
const u = queue.dequeue();
28+
const neighbors = adjList.get(u);
2829
color[u] = Colors.GREY;
2930
for (let i = 0; i < neighbors.length; i++) {
3031
const w = neighbors[i];
@@ -40,7 +41,7 @@ export const breadthFirstSearch = (graph: Graph, callback: Function) => {
4041
}
4142
};
4243

43-
export const bfs = (graph: Graph, startVertex: number) => {
44+
export const bfs = (graph: Graph, startVertex: any) => {
4445
const vertices = graph.getVertices();
4546
const adjList = graph.getAdjList();
4647
const color = initializeColor(vertices);

src/ts/algorithms/graph/depth-first-search.ts

+13-14
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,12 @@ const DFSVisit = (
5454
d: any,
5555
f: any,
5656
p: any,
57-
time: number,
57+
time: any,
5858
adjList: any
5959
) => {
6060
// console.log('discovered ' + u);
6161
color[u] = Colors.GREY;
62-
d[u] = ++time;
62+
d[u] = ++time.count;
6363
const neighbors = adjList.get(u);
6464
for (let i = 0; i < neighbors.length; i++) {
6565
const w = neighbors[i];
@@ -69,35 +69,34 @@ const DFSVisit = (
6969
}
7070
}
7171
color[u] = Colors.BLACK;
72-
f[u] = ++time;
72+
f[u] = ++time.count;
7373
// console.log('explored ' + u);
7474
};
7575

7676
export const DFS = (graph: Graph) => {
77-
7877
const vertices = graph.getVertices();
7978
const adjList = graph.getAdjList();
8079
const color = initializeColor(vertices);
8180
const d: any = {};
8281
const f: any = {};
8382
const p: any = {};
84-
const time = 0;
83+
const time = { count: 0 };
8584

8685
for (let i = 0; i < vertices.length; i++) {
87-
f[vertices[i]] = 0;
88-
d[vertices[i]] = 0;
89-
p[vertices[i]] = null;
86+
f[vertices[i]] = 0;
87+
d[vertices[i]] = 0;
88+
p[vertices[i]] = null;
9089
}
9190

9291
for (let i = 0; i < vertices.length; i++) {
93-
if (color[vertices[i]] === Colors.WHITE) {
94-
DFSVisit(vertices[i], color, d, f, p, time, adjList);
95-
}
92+
if (color[vertices[i]] === Colors.WHITE) {
93+
DFSVisit(vertices[i], color, d, f, p, time, adjList);
94+
}
9695
}
9796

9897
return {
99-
discovery: d,
100-
finished: f,
101-
predecessors: p
98+
discovery: d,
99+
finished: f,
100+
predecessors: p
102101
};
103102
};

src/ts/data-structures/graph.ts

+1-4
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,10 @@ export default class Graph {
2020
if (!this.adjList.get(b)) {
2121
this.addVertex(b);
2222
}
23-
2423
this.adjList.get(a).push(b);
25-
26-
if (!this.isDirected) {
24+
if (this.isDirected !== true) {
2725
this.adjList.get(b).push(a);
2826
}
29-
// adjList.get(w).push(v); //commented to run the improved DFS with topological sorting
3027
}
3128

3229
getVertices() {

src/ts/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import * as _util from './util';
22
export const util = _util;
33

4+
export { default as Stack } from './data-structures/stack';
5+
46
export { default as LinkedList } from './data-structures/linked-list';
57
export { default as DoublyLinkedList } from './data-structures/doubly-linked-list';
68
export { default as CircularLinkedList } from './data-structures/circular-linked-list';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import 'mocha';
2+
import { expect } from 'chai';
3+
import { BFS, breadthFirstSearch, Graph } from '../../../../src/js/index';
4+
5+
describe('Breadth First Search', () => {
6+
let count;
7+
const vertices = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I'];
8+
let graph;
9+
10+
function assertCallback(value) {
11+
expect(value).to.equal(vertices[count]);
12+
count++;
13+
}
14+
15+
beforeEach(() => {
16+
count = 0;
17+
graph = new Graph();
18+
19+
for (let i = 0; i < vertices.length; i++) {
20+
graph.addVertex(vertices[i]);
21+
}
22+
23+
graph.addEdge('A', 'B');
24+
graph.addEdge('A', 'C');
25+
graph.addEdge('A', 'D');
26+
graph.addEdge('C', 'D');
27+
graph.addEdge('C', 'G');
28+
graph.addEdge('D', 'G');
29+
graph.addEdge('D', 'H');
30+
graph.addEdge('B', 'E');
31+
graph.addEdge('B', 'F');
32+
graph.addEdge('E', 'I');
33+
});
34+
35+
it('breadthFirstSearch', () => {
36+
breadthFirstSearch(graph, vertices[0], assertCallback);
37+
});
38+
39+
it('sorthest path - BFS', () => {
40+
const shortestPathA = BFS(graph, vertices[0]);
41+
42+
expect(shortestPathA.distances).to.deep.equal({
43+
A: 0,
44+
B: 1,
45+
C: 1,
46+
D: 1,
47+
E: 2,
48+
F: 2,
49+
G: 2,
50+
H: 2,
51+
I: 3
52+
});
53+
expect(shortestPathA.predecessors).to.deep.equal({
54+
A: null,
55+
B: 'A',
56+
C: 'A',
57+
D: 'A',
58+
E: 'B',
59+
F: 'B',
60+
G: 'C',
61+
H: 'D',
62+
I: 'E'
63+
});
64+
});
65+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import 'mocha';
2+
import { expect } from 'chai';
3+
import { DFS, depthFirstSearch, Graph } from '../../../../src/js/index';
4+
5+
describe('Depth First Search', () => {
6+
let count;
7+
const vertices = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I'];
8+
const dfsCallBack = ['A', 'B', 'E', 'I', 'F', 'C', 'D', 'G', 'H'];
9+
let graph;
10+
11+
beforeEach(() => {
12+
count = 0;
13+
graph = new Graph(true);
14+
});
15+
16+
function assertCallback(value) {
17+
expect(value).to.equal(dfsCallBack[count]);
18+
count++;
19+
}
20+
21+
it('depthFirstSearch', () => {
22+
for (let i = 0; i < vertices.length; i++) {
23+
graph.addVertex(vertices[i]);
24+
}
25+
26+
graph.addEdge('A', 'B');
27+
graph.addEdge('A', 'C');
28+
graph.addEdge('A', 'D');
29+
graph.addEdge('C', 'D');
30+
graph.addEdge('C', 'G');
31+
graph.addEdge('D', 'G');
32+
graph.addEdge('D', 'H');
33+
graph.addEdge('B', 'E');
34+
graph.addEdge('B', 'F');
35+
graph.addEdge('E', 'I');
36+
37+
depthFirstSearch(graph, assertCallback);
38+
});
39+
40+
it('topological sort - DFS', () => {
41+
const myVertices = ['A', 'B', 'C', 'D', 'E', 'F'];
42+
for (let i = 0; i < myVertices.length; i++) {
43+
graph.addVertex(myVertices[i]);
44+
}
45+
graph.addEdge('A', 'C');
46+
graph.addEdge('A', 'D');
47+
graph.addEdge('B', 'D');
48+
graph.addEdge('B', 'E');
49+
graph.addEdge('C', 'F');
50+
graph.addEdge('F', 'E');
51+
52+
const result = DFS(graph);
53+
54+
expect(result.discovery).to.deep.equal({
55+
A: 1, B: 11, C: 2, D: 8, E: 4, F: 3
56+
});
57+
expect(result.finished).to.deep.equal({
58+
A: 10, B: 12, C: 7, D: 9, E: 5, F: 6
59+
});
60+
expect(result.predecessors).to.deep.equal({
61+
A: null, B: null, C: 'A', D: 'A', E: 'F', F: 'C'
62+
});
63+
});
64+
});
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import 'mocha';
2+
import { expect } from 'chai';
3+
import { dijkstra } from '../../../../src/js/index';
4+
5+
describe('Dijkstra\'s Algorithm - Shortest Path', () => {
6+
7+
it('Shortest Path', () => {
8+
const graph = [
9+
[0, 2, 4, 0, 0, 0],
10+
[0, 0, 2, 4, 2, 0],
11+
[0, 0, 0, 0, 3, 0],
12+
[0, 0, 0, 0, 0, 2],
13+
[0, 0, 0, 3, 0, 2],
14+
[0, 0, 0, 0, 0, 0]
15+
];
16+
17+
expect(dijkstra(graph, 0)).to.deep.equal([0, 2, 4, 6, 4, 6]);
18+
19+
});
20+
21+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import 'mocha';
2+
import { expect } from 'chai';
3+
import { floydWarshall } from '../../../../src/js/index';
4+
5+
describe('Floyd-Warshall Algorithm - All-Pairs Shortest Path', () => {
6+
it('All-Pairs Shortest Path', () => {
7+
const INF = Infinity;
8+
const graph = [
9+
[INF, 2, 4, INF, INF, INF],
10+
[INF, INF, 2, 4, 2, INF],
11+
[INF, INF, INF, INF, 3, INF],
12+
[INF, INF, INF, INF, INF, 2],
13+
[INF, INF, INF, 3, INF, 2],
14+
[INF, INF, INF, INF, INF, INF]
15+
];
16+
17+
expect(floydWarshall(graph)).to.deep.equal([
18+
[0, 2, 4, 6, 4, 6],
19+
[INF, 0, 2, 4, 2, 4],
20+
[INF, INF, 0, 6, 3, 5],
21+
[INF, INF, INF, 0, INF, 2],
22+
[INF, INF, INF, 3, 0, 2],
23+
[INF, INF, INF, INF, INF, 0]
24+
]);
25+
});
26+
});
+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import 'mocha';
2+
import { expect } from 'chai';
3+
import { kruskal } from '../../../../src/js/index';
4+
5+
describe('Kruskal Algorithm - Minimum Spanning Tree', () => {
6+
it('Minimum Spanning Tree', () => {
7+
const graph = [
8+
[0, 2, 4, 0, 0, 0],
9+
[2, 0, 2, 4, 2, 0],
10+
[4, 2, 0, 0, 3, 0],
11+
[0, 4, 0, 0, 3, 2],
12+
[0, 2, 3, 3, 0, 2],
13+
[0, 0, 0, 2, 2, 0]
14+
];
15+
16+
expect(kruskal(graph)).to.deep.equal([ , 0, 1, 1, 1, 3]);
17+
});
18+
});

test/js/algorithms/graph/prim.spec.js

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import 'mocha';
2+
import { expect } from 'chai';
3+
import { prim } from '../../../../src/js/index';
4+
5+
describe('Prim\'s Algorithm - Minimum Spanning Tree', () => {
6+
it('Minimum Spanning Tree', () => {
7+
const graph = [
8+
[0, 2, 4, 0, 0, 0],
9+
[2, 0, 2, 4, 2, 0],
10+
[4, 2, 0, 0, 3, 0],
11+
[0, 4, 0, 0, 3, 2],
12+
[0, 2, 3, 3, 0, 2],
13+
[0, 0, 0, 2, 2, 0]
14+
];
15+
16+
expect(prim(graph)).to.deep.equal([-1, 0, 1, 5, 1, 4]);
17+
});
18+
});

0 commit comments

Comments
 (0)