Skip to content

Commit 683c8fe

Browse files
committed
add find & depth first search (in order and reverse in order implemented so far)
1 parent c2c3bbc commit 683c8fe

File tree

4 files changed

+228
-28
lines changed

4 files changed

+228
-28
lines changed

dist/datastructures/BinarySearchTree.js

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class BinarySearchTree {
2020
return node;
2121
}
2222
let targetNode = this.root;
23-
while (targetNode) {
23+
while (true) {
2424
if (node.value < targetNode.value) {
2525
if (!targetNode.left) {
2626
targetNode.left = node;
@@ -36,7 +36,61 @@ class BinarySearchTree {
3636
targetNode = targetNode.right;
3737
}
3838
}
39-
return node;
39+
}
40+
find(value, startingNode = this.root) {
41+
if (!startingNode)
42+
return null;
43+
if (value < startingNode.value) {
44+
return this.find(value, startingNode.left);
45+
}
46+
if (value > startingNode.value) {
47+
return this.find(value, startingNode.right);
48+
}
49+
// found!
50+
return startingNode;
51+
}
52+
DFS(startingNode = this.root, options = { order: 'ascending' }) {
53+
if (startingNode === null)
54+
return null;
55+
const array = [];
56+
const helper = (node = startingNode, options = { order: 'ascending' }) => {
57+
const { order } = options;
58+
if (order === 'ascending') {
59+
if (node.left)
60+
helper(node.left);
61+
array.push(node.value);
62+
if (node.right)
63+
helper(node.right);
64+
}
65+
if (order === 'descending') {
66+
if (node.right)
67+
helper(node.right, { order: 'descending' });
68+
array.push(node.value);
69+
if (node.left)
70+
helper(node.left, { order: 'descending' });
71+
}
72+
};
73+
helper(startingNode, options);
74+
return array;
75+
}
76+
logTree(startingNode = this.root, options = { order: 'ascending' }) {
77+
if (!startingNode)
78+
return console.log(null);
79+
const { order } = options;
80+
if (order === 'ascending') {
81+
if (startingNode.left)
82+
this.logTree(startingNode.left);
83+
console.log(startingNode.value);
84+
if (startingNode.right)
85+
this.logTree(startingNode.right);
86+
}
87+
if (order === 'descending') {
88+
if (startingNode.right)
89+
return this.logTree(startingNode.right, { order: 'descending' });
90+
console.log(startingNode.value);
91+
if (startingNode.left)
92+
return this.logTree(startingNode.left, { order: 'descending' });
93+
}
4094
}
4195
}
4296
exports.default = BinarySearchTree;

dist/datastructures/BinarySearchTree.test.js

Lines changed: 59 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,15 @@ var __importStar = (this && this.__importStar) || function (mod) {
88
};
99
Object.defineProperty(exports, "__esModule", { value: true });
1010
const BinarySearchTree_1 = __importStar(require("./BinarySearchTree"));
11+
function populateTree(tree) {
12+
BST.insert(5);
13+
BST.insert(3);
14+
BST.insert(8);
15+
BST.insert(4);
16+
BST.insert(6);
17+
BST.insert(1);
18+
BST.insert(9);
19+
}
1120
let BST = new BinarySearchTree_1.default();
1221
beforeEach(() => BST = new BinarySearchTree_1.default());
1322
describe('basic binary search tree functionality', () => {
@@ -34,21 +43,62 @@ describe('basic binary search tree functionality', () => {
3443
test('Insert method exists', () => {
3544
expect(typeof BST.insert).toBe('function');
3645
});
46+
});
47+
describe('insertion', () => {
3748
test('insert method works by inserting in order (left to right ascending)', () => {
3849
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
39-
BST.insert(5);
50+
populateTree(BST);
4051
expect((_a = BST.root) === null || _a === void 0 ? void 0 : _a.value).toBe(5);
41-
BST.insert(3);
4252
expect((_c = (_b = BST.root) === null || _b === void 0 ? void 0 : _b.left) === null || _c === void 0 ? void 0 : _c.value).toBe(3);
43-
BST.insert(7);
44-
expect((_e = (_d = BST.root) === null || _d === void 0 ? void 0 : _d.right) === null || _e === void 0 ? void 0 : _e.value).toBe(7);
45-
BST.insert(4);
53+
expect((_e = (_d = BST.root) === null || _d === void 0 ? void 0 : _d.right) === null || _e === void 0 ? void 0 : _e.value).toBe(8);
4654
expect((_h = (_g = (_f = BST.root) === null || _f === void 0 ? void 0 : _f.left) === null || _g === void 0 ? void 0 : _g.right) === null || _h === void 0 ? void 0 : _h.value).toBe(4);
47-
BST.insert(6);
4855
expect((_l = (_k = (_j = BST.root) === null || _j === void 0 ? void 0 : _j.right) === null || _k === void 0 ? void 0 : _k.left) === null || _l === void 0 ? void 0 : _l.value).toBe(6);
49-
BST.insert(1);
5056
expect((_p = (_o = (_m = BST.root) === null || _m === void 0 ? void 0 : _m.left) === null || _o === void 0 ? void 0 : _o.left) === null || _p === void 0 ? void 0 : _p.value).toBe(1);
51-
BST.insert(8);
52-
expect((_s = (_r = (_q = BST.root) === null || _q === void 0 ? void 0 : _q.right) === null || _r === void 0 ? void 0 : _r.right) === null || _s === void 0 ? void 0 : _s.value).toBe(8);
57+
expect((_s = (_r = (_q = BST.root) === null || _q === void 0 ? void 0 : _q.right) === null || _r === void 0 ? void 0 : _r.right) === null || _s === void 0 ? void 0 : _s.value).toBe(9);
58+
});
59+
test(`can insert multiple nodes of the same value and they'll bubble down the right`, () => {
60+
var _a, _b, _c, _d, _e, _f;
61+
BST.insert(1);
62+
BST.insert(1);
63+
BST.insert(1);
64+
expect((_a = BST.root) === null || _a === void 0 ? void 0 : _a.value).toBe(1);
65+
expect((_c = (_b = BST.root) === null || _b === void 0 ? void 0 : _b.right) === null || _c === void 0 ? void 0 : _c.value).toBe(1);
66+
expect((_f = (_e = (_d = BST.root) === null || _d === void 0 ? void 0 : _d.right) === null || _e === void 0 ? void 0 : _e.right) === null || _f === void 0 ? void 0 : _f.value).toBe(1);
67+
});
68+
});
69+
describe('binary search', () => {
70+
test('searching for a value in a empty tree returns null', () => {
71+
expect(BST.find(1)).toBeNull();
72+
});
73+
test('searching for a value which is the root value', () => {
74+
var _a;
75+
BST.insert(1);
76+
expect((_a = BST.find(1)) === null || _a === void 0 ? void 0 : _a.value).toBe(1);
77+
});
78+
test('searching a populated tree', () => {
79+
var _a, _b, _c, _d, _e, _f, _g;
80+
populateTree(BST);
81+
expect((_a = BST.find(1)) === null || _a === void 0 ? void 0 : _a.value).toBe(1);
82+
expect(BST.find(2)).toBeNull();
83+
expect((_b = BST.find(3)) === null || _b === void 0 ? void 0 : _b.value).toBe(3);
84+
expect((_c = BST.find(4)) === null || _c === void 0 ? void 0 : _c.value).toBe(4);
85+
expect((_d = BST.find(5)) === null || _d === void 0 ? void 0 : _d.value).toBe(5);
86+
expect((_e = BST.find(6)) === null || _e === void 0 ? void 0 : _e.value).toBe(6);
87+
expect(BST.find(7)).toBeNull();
88+
expect((_f = BST.find(8)) === null || _f === void 0 ? void 0 : _f.value).toBe(8);
89+
expect((_g = BST.find(9)) === null || _g === void 0 ? void 0 : _g.value).toBe(9);
90+
});
91+
});
92+
describe('depth first search', () => {
93+
test('can log an empty tree', () => {
94+
});
95+
test('can log a populated tree in ascending order', () => {
96+
populateTree(BST);
97+
expect(BST.DFS()).toEqual([1, 3, 4, 5, 6, 8, 9]);
98+
});
99+
test('can log a populated tree in descending order', () => {
100+
populateTree(BST);
101+
console.log(BST.DFS(BST.root, { order: 'descending' }));
102+
expect(BST.DFS(BST.root, { order: 'descending' })).toEqual([9, 8, 6, 5, 4, 3, 1]);
53103
});
54104
});
Lines changed: 66 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,96 @@
11
import BinarySearchTree, { BinaryTreeNode } from './BinarySearchTree';
22

3+
function populateTree<T>(tree: BinarySearchTree<T>): void {
4+
BST.insert(5);
5+
BST.insert(3);
6+
BST.insert(8);
7+
BST.insert(4);
8+
BST.insert(6);
9+
BST.insert(1);
10+
BST.insert(9);
11+
}
12+
313
let BST = new BinarySearchTree<number>();
414
beforeEach(() => BST = new BinarySearchTree<number>());
515

616
describe('basic binary search tree functionality', () => {
717
test('Binary search tree exists', () => {
818
expect(BST).toBeTruthy();
9-
})
19+
});
1020
test('Tree root initiates as null', () => {
1121
expect(BST.root).toBeNull();
12-
})
22+
});
1323
test('Can add new root node to tree', () => {
1424
const node = new BinaryTreeNode(5);
1525
BST.root = node;
1626
expect(BST.root?.value).toBe(5);
17-
})
27+
});
1828
test('Can add left and right nodes to tree root manually', () => {
1929
BST.root = new BinaryTreeNode(5);
2030
BST.root.left = new BinaryTreeNode(1);
2131
BST.root.right = new BinaryTreeNode(10);
2232
expect(BST.root?.left?.value).toBe(1);
2333
expect(BST.root?.right?.value).toBe(10);
24-
})
34+
});
2535
test('Insert method exists', () => {
2636
expect(typeof BST.insert).toBe('function');
27-
})
37+
});
38+
})
39+
40+
describe('insertion', () => {
2841
test('insert method works by inserting in order (left to right ascending)', () => {
29-
BST.insert(5);
42+
populateTree(BST);
3043
expect(BST.root?.value).toBe(5);
31-
BST.insert(3);
3244
expect(BST.root?.left?.value).toBe(3);
33-
BST.insert(7);
34-
expect(BST.root?.right?.value).toBe(7);
35-
BST.insert(4);
45+
expect(BST.root?.right?.value).toBe(8);
3646
expect(BST.root?.left?.right?.value).toBe(4);
37-
BST.insert(6);
3847
expect(BST.root?.right?.left?.value).toBe(6);
39-
BST.insert(1);
4048
expect(BST.root?.left?.left?.value).toBe(1);
41-
BST.insert(8);
42-
expect(BST.root?.right?.right?.value).toBe(8);
49+
expect(BST.root?.right?.right?.value).toBe(9);
50+
});
51+
test(`can insert multiple nodes of the same value and they'll bubble down the right`, () => {
52+
BST.insert(1);
53+
BST.insert(1);
54+
BST.insert(1);
55+
expect(BST.root?.value).toBe(1);
56+
expect(BST.root?.right?.value).toBe(1);
57+
expect(BST.root?.right?.right?.value).toBe(1);
58+
});
59+
})
60+
61+
describe('binary search', () => {
62+
test('searching for a value in a empty tree returns null', () => {
63+
expect(BST.find(1)).toBeNull();
64+
})
65+
test('searching for a value which is the root value', () => {
66+
BST.insert(1);
67+
expect(BST.find(1)?.value).toBe(1);
68+
});
69+
test('searching a populated tree', () => {
70+
populateTree(BST);
71+
expect(BST.find(1)?.value).toBe(1);
72+
expect(BST.find(2)).toBeNull();
73+
expect(BST.find(3)?.value).toBe(3);
74+
expect(BST.find(4)?.value).toBe(4);
75+
expect(BST.find(5)?.value).toBe(5);
76+
expect(BST.find(6)?.value).toBe(6);
77+
expect(BST.find(7)).toBeNull();
78+
expect(BST.find(8)?.value).toBe(8);
79+
expect(BST.find(9)?.value).toBe(9);
80+
})
81+
})
82+
83+
describe('depth first search', () => {
84+
test('can log an empty tree', () => {
85+
86+
})
87+
test('can log a populated tree in ascending order', () => {
88+
populateTree(BST);
89+
expect(BST.DFS()).toEqual([1, 3, 4, 5, 6, 8, 9]);
90+
})
91+
test('can log a populated tree in descending order', () => {
92+
populateTree(BST);
93+
console.log(BST.DFS(BST.root, { order: 'descending' }));
94+
expect(BST.DFS(BST.root, { order: 'descending' })).toEqual([9, 8, 6, 5, 4, 3, 1]);
4395
})
4496
})

src/datastructures/BinarySearchTree.ts

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ class BinaryTreeNode<T> {
88
constructor(value: T) {
99
this.left = null;
1010
this.right = null;
11-
this.value = value;
11+
this.value = value as T;
1212
}
1313
}
1414

@@ -31,7 +31,7 @@ class BinarySearchTree<T> {
3131
return node;
3232
}
3333
let targetNode: BinaryTreeNode<T> = this.root;
34-
while (targetNode) {
34+
while (true) {
3535
if (node.value < targetNode.value) {
3636
if (!targetNode.left) {
3737
targetNode.left = node;
@@ -47,7 +47,51 @@ class BinarySearchTree<T> {
4747
targetNode = targetNode.right;
4848
}
4949
}
50-
return node;
50+
}
51+
find(value: T, startingNode: BinaryTreeNode<T> | null = this.root): BinaryTreeNode<T> | null {
52+
if (!startingNode) return null;
53+
if (value < startingNode.value) {
54+
return this.find(value, startingNode.left)
55+
}
56+
if (value > startingNode.value) {
57+
return this.find(value, startingNode.right)
58+
}
59+
// found!
60+
return startingNode;
61+
}
62+
63+
DFS(startingNode: BinaryTreeNode<T> | null = this.root, options = { order: 'ascending' }): T[] | null {
64+
if (startingNode === null) return null;
65+
const array: T[] = [];
66+
const helper = (node: BinaryTreeNode<T> = startingNode, options = { order: 'ascending' }): void => {
67+
const { order } = options;
68+
if (order === 'ascending') {
69+
if (node.left) helper(node.left);
70+
array.push(node.value);
71+
if (node.right) helper(node.right);
72+
}
73+
if (order === 'descending') {
74+
if (node.right) helper(node.right, { order: 'descending' });
75+
array.push(node.value);
76+
if (node.left) helper(node.left, { order: 'descending' });
77+
}
78+
};
79+
helper(startingNode, options);
80+
return array;
81+
}
82+
logTree(startingNode: BinaryTreeNode<T> | null = this.root, options = { order: 'ascending' }): void {
83+
if (!startingNode) return console.log(null);
84+
const { order } = options;
85+
if (order === 'ascending') {
86+
if (startingNode.left) this.logTree(startingNode.left);
87+
console.log(startingNode.value);
88+
if (startingNode.right) this.logTree(startingNode.right);
89+
}
90+
if (order === 'descending') {
91+
if (startingNode.right) return this.logTree(startingNode.right, { order: 'descending' });
92+
console.log(startingNode.value);
93+
if (startingNode.left) return this.logTree(startingNode.left, { order: 'descending' });
94+
}
5195
}
5296
}
5397

0 commit comments

Comments
 (0)