Skip to content

Commit 797a6f2

Browse files
committed
Make it possible to use objects as a values for binary search tree nodes.
1 parent 3ae9c40 commit 797a6f2

File tree

3 files changed

+82
-7
lines changed

3 files changed

+82
-7
lines changed

src/data-structures/tree/binary-search-tree/BinarySearchTree.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,31 @@ export default class BinarySearchTree {
55
this.root = new BinarySearchTreeNode();
66
}
77

8+
/**
9+
* @param {*} value
10+
*/
811
insert(value) {
912
this.root.insert(value);
1013
}
1114

15+
/**
16+
* @param {*} value
17+
* @return {boolean}
18+
*/
1219
contains(value) {
1320
return this.root.contains(value);
1421
}
1522

23+
/**
24+
* @param {*} value
25+
*/
1626
remove(value) {
1727
return this.root.remove(value);
1828
}
1929

30+
/**
31+
* @return {string}
32+
*/
2033
toString() {
2134
return this.root.toString();
2235
}

src/data-structures/tree/binary-search-tree/BinarySearchTreeNode.js

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,37 @@
11
import BinaryTreeNode from '../BinaryTreeNode';
2+
import Comparator from '../../../utils/comparator/Comparator';
23

34
export default class BinarySearchTreeNode extends BinaryTreeNode {
5+
/**
6+
* @param {*} value
7+
* @param {BinaryTreeNode} parent
8+
* @param {function} compareFunction
9+
*/
10+
constructor(value = null, parent = null, compareFunction = undefined) {
11+
super(value, parent);
12+
13+
// This comparator is used to compare node values with each other.
14+
this.nodeValueComparator = new Comparator(compareFunction);
15+
}
16+
17+
/**
18+
* @param {*} value
19+
* @return {BinarySearchTreeNode}
20+
*/
421
insert(value) {
5-
if (this.value === null) {
22+
if (this.nodeValueComparator.equal(this.value, null)) {
623
this.value = value;
724
return this;
825
}
926

10-
if (value < this.value) {
27+
if (this.nodeValueComparator.lessThan(value, this.value)) {
1128
// Insert to the left.
1229
if (this.left) {
1330
this.left.insert(value);
1431
} else {
1532
this.setLeft(new BinarySearchTreeNode(value));
1633
}
17-
} else if (value > this.value) {
34+
} else if (this.nodeValueComparator.greaterThan(value, this.value)) {
1835
// Insert to the right.
1936
if (this.right) {
2037
this.right.insert(value);
@@ -26,27 +43,38 @@ export default class BinarySearchTreeNode extends BinaryTreeNode {
2643
return this;
2744
}
2845

46+
/**
47+
* @param {*} value
48+
* @return {BinarySearchTreeNode}
49+
*/
2950
find(value) {
3051
// Check the root.
31-
if (this.value === value) {
52+
if (this.nodeValueComparator.equal(this.value, value)) {
3253
return this;
3354
}
3455

35-
if (value < this.value && this.left) {
56+
if (this.nodeValueComparator.lessThan(value, this.value) && this.left) {
3657
// Check left nodes.
3758
return this.left.find(value);
38-
} else if (value > this.value && this.right) {
59+
} else if (this.nodeValueComparator.greaterThan(value, this.value) && this.right) {
3960
// Check right nodes.
4061
return this.right.find(value);
4162
}
4263

4364
return null;
4465
}
4566

67+
/**
68+
* @param {*} value
69+
* @return {boolean}
70+
*/
4671
contains(value) {
4772
return !!this.find(value);
4873
}
4974

75+
/**
76+
* @param {*} value
77+
*/
5078
remove(value) {
5179
const nodeToRemove = this.find(value);
5280

@@ -65,7 +93,7 @@ export default class BinarySearchTreeNode extends BinaryTreeNode {
6593
// Find the next biggest value (minimum value in the right branch)
6694
// and replace current value node with that next biggest value.
6795
const nextBiggerNode = nodeToRemove.right.findMin();
68-
if (nextBiggerNode !== nodeToRemove.right) {
96+
if (!this.nodeComparator.equal(nextBiggerNode, nodeToRemove.right)) {
6997
this.remove(nextBiggerNode.value);
7098
nodeToRemove.value = nextBiggerNode.value;
7199
} else {
@@ -85,6 +113,9 @@ export default class BinarySearchTreeNode extends BinaryTreeNode {
85113
}
86114
}
87115

116+
/**
117+
* @return {BinarySearchTreeNode}
118+
*/
88119
findMin() {
89120
if (!this.left) {
90121
return this;

src/data-structures/tree/binary-search-tree/__test__/BinarySearchTreeNode.test.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,4 +171,35 @@ describe('BinarySearchTreeNode', () => {
171171

172172
expect(removeNotExistingElementFromTree).toThrow();
173173
});
174+
175+
it('should be possible to use objects as node values', () => {
176+
const nodeValueComparatorCallback = (a, b) => {
177+
const normalizedA = a || { value: null };
178+
const normalizedB = b || { value: null };
179+
180+
if (normalizedA.value === normalizedB.value) {
181+
return 0;
182+
}
183+
184+
return normalizedA.value < normalizedB.value ? -1 : 1;
185+
};
186+
187+
const obj1 = { key: 'obj1', value: 1, toString: () => 'obj1' };
188+
const obj2 = { key: 'obj2', value: 2, toString: () => 'obj2' };
189+
const obj3 = { key: 'obj3', value: 3, toString: () => 'obj3' };
190+
191+
const bstNode = new BinarySearchTreeNode(obj2, null, nodeValueComparatorCallback);
192+
bstNode.insert(obj1);
193+
194+
expect(bstNode.toString()).toBe('obj1,obj2');
195+
expect(bstNode.contains(obj1)).toBeTruthy();
196+
expect(bstNode.contains(obj3)).toBeFalsy();
197+
198+
bstNode.insert(obj3);
199+
200+
expect(bstNode.toString()).toBe('obj1,obj2,obj3');
201+
expect(bstNode.contains(obj3)).toBeTruthy();
202+
203+
expect(bstNode.findMin().value).toEqual(obj1);
204+
});
174205
});

0 commit comments

Comments
 (0)