Skip to content

Commit 7b9d6f8

Browse files
committed
update code graph implement DSA and its unitest
1 parent 53a480a commit 7b9d6f8

File tree

5 files changed

+361
-0
lines changed

5 files changed

+361
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
class PriorityQueue {
2+
heap: number[];
3+
constructor() {
4+
this.heap = [];
5+
}
6+
7+
// Helper Methods
8+
getLeftChildIndex(parentIndex: number) {
9+
return 2 * parentIndex + 1;
10+
}
11+
12+
getRightChildIndex(parentIndex: number) {
13+
return 2 * parentIndex + 2;
14+
}
15+
16+
getParentIndex(childIndex: number) {
17+
return Math.floor((childIndex - 1) / 2);
18+
}
19+
20+
hasLeftChild(index: number) {
21+
return this.getLeftChildIndex(index)
22+
< this.heap.length;
23+
}
24+
25+
hasRightChild(index: number) {
26+
return this.getRightChildIndex(index)
27+
< this.heap.length;
28+
}
29+
30+
hasParent(index: number) {
31+
return this.getParentIndex(index) >= 0;
32+
}
33+
34+
leftChild(index: number) {
35+
return this.heap[this.getLeftChildIndex(index)];
36+
}
37+
38+
rightChild(index: number) {
39+
return this.heap[this.getRightChildIndex(index)];
40+
}
41+
42+
parent(index: number) {
43+
return this.heap[this.getParentIndex(index)];
44+
}
45+
46+
swap(indexOne: number, indexTwo: number) {
47+
const temp = this.heap[indexOne];
48+
this.heap[indexOne] = this.heap[indexTwo];
49+
this.heap[indexTwo] = temp;
50+
}
51+
52+
peek() {
53+
if (this.heap.length === 0) {
54+
return null;
55+
}
56+
return this.heap[0];
57+
}
58+
59+
// Removing an element will remove the
60+
// top element with highest priority then
61+
// heapifyDown will be called
62+
remove() {
63+
if (this.heap.length === 0) {
64+
return null;
65+
}
66+
const item = this.heap[0];
67+
this.heap[0] = this.heap[this.heap.length - 1];
68+
this.heap.pop();
69+
this.heapifyDown();
70+
return item;
71+
}
72+
73+
add(item: number) {
74+
this.heap.push(item);
75+
this.heapifyUp();
76+
}
77+
78+
heapifyUp() {
79+
let index = this.heap.length - 1;
80+
while (this.hasParent(index) && this.parent(index)
81+
< this.heap[index]) {
82+
this.swap(this.getParentIndex(index), index);
83+
index = this.getParentIndex(index);
84+
}
85+
}
86+
87+
heapifyDown() {
88+
let index = 0;
89+
while (this.hasLeftChild(index)) {
90+
let smallerChildIndex = this.getLeftChildIndex(index);
91+
if (this.hasRightChild(index) && this.rightChild(index)
92+
> this.leftChild(index)) {
93+
smallerChildIndex = this.getRightChildIndex(index);
94+
}
95+
if (this.heap[index] > this.heap[smallerChildIndex]) {
96+
break;
97+
} else {
98+
this.swap(index, smallerChildIndex);
99+
}
100+
index = smallerChildIndex;
101+
}
102+
}
103+
}
104+
105+
// Creating The Priority Queue
106+
let PriQueue = new PriorityQueue();
107+
PriQueue.add(32);
108+
PriQueue.add(45);
109+
PriQueue.add(12);
110+
PriQueue.add(65);
111+
PriQueue.add(85);
112+
console.log("priQueue", PriQueue);
113+
// Removing and Checking elements of highest Priority
114+
console.log(PriQueue.peek());
115+
console.log(PriQueue.remove());
116+
console.log(PriQueue.peek());
117+
console.log(PriQueue.remove());
118+
console.log(PriQueue.peek());
119+
console.log(PriQueue.remove());

src/data_structure/binarySearchTree/heap/min-heap.ts

Whitespace-only changes.
+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
2+
// 3 concepts to build a graph
3+
// Edge List
4+
const graphEdge = [
5+
[0, 2],
6+
[2, 3],
7+
[2, 1],
8+
[1, 3],
9+
];
10+
11+
// Adjacent List
12+
const graphAjacent = [[2], [2, 3], [0, 1, 3], [1, 2]];
13+
const mapGraphAdjacent = {
14+
0: [2],
15+
1: [2, 3],
16+
2: [0, 1, 3],
17+
3: [1, 2],
18+
}
19+
20+
const mapGraphAdjacentWeighted = {
21+
0: [[1, 99], [2, 50]],
22+
1: [[2, 50], [3, 50], [4, 50]],
23+
2: [[3, 99]],
24+
3: [[4, 75]],
25+
4: [],
26+
}
27+
28+
// Adjacent Matrix
29+
const graphAdjectMatrix = [
30+
[0, 0, 1, 0],
31+
[0, 0, 1, 1],
32+
[1, 1, 0, 1],
33+
[0, 1, 1, 0],
34+
];
35+
36+
// Adjacent Matrix
37+
const graphExample = {
38+
0: [0, 0, 0, 0, 0],
39+
1: [99, 9, 0, 0, 0],
40+
2: [50, 50, 0, 0, 0],
41+
3: [0, 0, 50, 0, 0],
42+
4: [0, 0, 0, 75, 0],
43+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
import { describe, it, expect, beforeEach, afterEach } from 'bun:test';
2+
import { Graph } from './graph-implement';
3+
4+
describe('Graph', () => {
5+
let graph: Graph;
6+
7+
beforeEach(() => {
8+
graph = new Graph();
9+
});
10+
11+
it('should add a new vertex to the graph', () => {
12+
graph.addVertex('A');
13+
expect(graph.adjacentList['A']).toBeDefined();
14+
expect(graph.numberOfNodes).toBe(1);
15+
});
16+
17+
it('should not increase nodes count when adding duplicate vertex', () => {
18+
graph.addVertex('A');
19+
graph.addVertex('A');
20+
expect(graph.numberOfNodes).toBe(1);
21+
});
22+
23+
it('should create an empty array for the new vertex', () => {
24+
graph.addVertex('A');
25+
expect(graph.adjacentList['A']).toEqual([]);
26+
});
27+
28+
it('should add an edge between two existing vertices', () => {
29+
graph.addVertex('A');
30+
graph.addVertex('B');
31+
graph.addEdge('A', 'B');
32+
expect(graph.adjacentList['A']).toContain('B');
33+
expect(graph.adjacentList['B']).toContain('A');
34+
});
35+
36+
it('should not add edge if vertices do not exist', () => {
37+
graph.addEdge('A', 'C');
38+
expect(graph.adjacentList['A']).toBeUndefined();
39+
});
40+
41+
it('should create undirected connections', () => {
42+
graph.addVertex('A');
43+
graph.addVertex('B');
44+
graph.addEdge('A', 'B');
45+
expect(graph.adjacentList['A']).toContain('B');
46+
expect(graph.adjacentList['B']).toContain('A');
47+
});
48+
49+
it('should handle multiple edges for a vertex', () => {
50+
graph.addVertex('A');
51+
graph.addVertex('B');
52+
graph.addVertex('C');
53+
graph.addVertex('D');
54+
graph.addEdge('A', 'B');
55+
graph.addEdge('A', 'C');
56+
graph.addEdge('B', 'D');
57+
58+
expect(graph.adjacentList['A']).toContain('B');
59+
expect(graph.adjacentList['A']).toContain('C');
60+
expect(graph.adjacentList['B']).toContain('A');
61+
expect(graph.adjacentList['B']).toContain('D');
62+
});
63+
64+
it('should maintain correct node count', () => {
65+
graph.addVertex('A');
66+
graph.addVertex('B');
67+
graph.addVertex('C');
68+
graph.addVertex('D');
69+
expect(graph.numberOfNodes).toBe(4);
70+
});
71+
72+
it('should handle adding edges to non-existent vertices silently', () => {
73+
graph.addEdge('X', 'Y');
74+
expect(graph.adjacentList['X']).toBeUndefined();
75+
expect(graph.adjacentList['Y']).toBeUndefined();
76+
});
77+
78+
it('should capture console output for showConnections', () => {
79+
// Capture console output
80+
const originalConsoleLog = console.log;
81+
const logs: string[] = [];
82+
83+
console.log = (message: string) => {
84+
logs.push(message);
85+
};
86+
87+
graph.addVertex('A');
88+
graph.addVertex('B');
89+
graph.addEdge('A', 'B');
90+
graph.showConnections();
91+
92+
// Restore original console.log
93+
console.log = originalConsoleLog;
94+
95+
expect(logs.length).toBeGreaterThan(0);
96+
expect(logs[0]).toContain('A-->');
97+
expect(logs[0]).toContain('B');
98+
});
99+
100+
it('should initialize with zero nodes', () => {
101+
expect(graph.numberOfNodes).toBe(0);
102+
});
103+
104+
it('should initialize with an empty adjacent list', () => {
105+
expect(Object.keys(graph.adjacentList).length).toBe(0);
106+
});
107+
108+
it('should not add duplicate edges', () => {
109+
graph.addVertex('A');
110+
graph.addVertex('B');
111+
graph.addVertex('C');
112+
graph.addVertex('D');
113+
graph.addEdge('A', 'B');
114+
graph.addEdge('B', 'A'); // Duplicate
115+
graph.addEdge('A', 'C');
116+
graph.addEdge('C', 'A'); // Duplicate
117+
graph.addEdge('B', 'D');
118+
119+
expect(graph.adjacentList['A']).toContain('B');
120+
expect(graph.adjacentList['A']).toContain('C');
121+
expect(graph.adjacentList['B']).toContain('A');
122+
expect(graph.adjacentList['B']).toContain('D');
123+
124+
const lengthA = graph.adjacentList['A'].length;
125+
const lengthB = graph.adjacentList['B'].length;
126+
const lengthC = graph.adjacentList['C'].length;
127+
const lengthD = graph.adjacentList['D'].length;
128+
expect(lengthA).toBe(2);
129+
expect(lengthB).toBe(2);
130+
expect(lengthC).toBe(1);
131+
expect(lengthD).toBe(1);
132+
});
133+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
export class Graph {
2+
numberOfNodes: number;
3+
adjacentList: any;
4+
constructor() {
5+
this.numberOfNodes = 0;
6+
this.adjacentList = {
7+
// Example: '0': ['1', '2]
8+
};
9+
}
10+
addVertex(node: string) {
11+
if (!this.adjacentList[node]) {
12+
this.adjacentList[node] = [];
13+
this.numberOfNodes++
14+
}
15+
}
16+
addEdge(node1: string, node2: string) {
17+
//undirected Graph
18+
if (this.adjacentList[node1] && this.adjacentList[node2]) {
19+
if (this.adjacentList[node1].indexOf(node2) === -1) {
20+
this.adjacentList[node1].push(node2);
21+
}
22+
if (this.adjacentList[node2].indexOf(node1) === -1) {
23+
this.adjacentList[node2].push(node1)
24+
}
25+
}
26+
}
27+
showConnections() {
28+
const allNodes = Object.keys(this.adjacentList);
29+
for (let node of allNodes) {
30+
let nodeConnections = this.adjacentList[node];
31+
let connections = "";
32+
let vertex;
33+
for (vertex of nodeConnections) {
34+
connections += vertex + " ";
35+
}
36+
console.log(node + "-->" + connections);
37+
}
38+
}
39+
}
40+
41+
const myGraph = new Graph();
42+
myGraph.addVertex('0');
43+
myGraph.addVertex('1');
44+
myGraph.addVertex('2');
45+
myGraph.addVertex('3');
46+
myGraph.addVertex('4');
47+
myGraph.addVertex('5');
48+
myGraph.addVertex('6');
49+
myGraph.addEdge('3', '1');
50+
myGraph.addEdge('3', '4');
51+
myGraph.addEdge('4', '2');
52+
myGraph.addEdge('4', '5');
53+
myGraph.addEdge('1', '2');
54+
myGraph.addEdge('1', '0');
55+
myGraph.addEdge('0', '2');
56+
myGraph.addEdge('6', '5');
57+
58+
myGraph.showConnections();
59+
//Answer:
60+
// 0-->1 2
61+
// 1-->3 2 0
62+
// 2-->4 1 0
63+
// 3-->1 4
64+
// 4-->3 2 5
65+
// 5-->4 6
66+
// 6-->5

0 commit comments

Comments
 (0)