Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 97e6120

Browse files
committedApr 4, 2018
Refactor BST.
1 parent 857edbf commit 97e6120

File tree

4 files changed

+119
-100
lines changed

4 files changed

+119
-100
lines changed
 

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

Lines changed: 1 addition & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -14,41 +14,7 @@ export default class BinarySearchTree {
1414
}
1515

1616
remove(value) {
17-
const nodeToRemove = this.root.find(value);
18-
19-
if (!nodeToRemove) {
20-
throw new Error('Item not found in the tree');
21-
}
22-
23-
const { parent } = nodeToRemove;
24-
25-
if (!nodeToRemove.left && !nodeToRemove.right) {
26-
// Node is a leaf and thus has no children.
27-
// Just remove the pointer to this node from the parent node.
28-
parent.removeChild(nodeToRemove);
29-
} else if (nodeToRemove.left && nodeToRemove.right) {
30-
// Node has two children.
31-
// Find the next biggest value (minimum value in the right branch)
32-
// and replace current value node with that next biggest value.
33-
const nextBiggerNode = nodeToRemove.right.findMin();
34-
if (nextBiggerNode !== nodeToRemove.right) {
35-
this.remove(nextBiggerNode.value);
36-
nodeToRemove.value = nextBiggerNode.value;
37-
} else {
38-
// In case if next right value is the next bigger one and it doesn't have left child
39-
// then just replace node that is going to be deleted with the right node.
40-
nodeToRemove.value = nodeToRemove.right.value;
41-
nodeToRemove.right = nodeToRemove.right.right;
42-
}
43-
} else {
44-
// Node has only one child.
45-
// Make this child to be a direct child of current node's parent.
46-
if (nodeToRemove.left) {
47-
parent.replaceChild(nodeToRemove, nodeToRemove.left);
48-
} else {
49-
parent.replaceChild(nodeToRemove, nodeToRemove.right);
50-
}
51-
}
17+
return this.root.remove(value);
5218
}
5319

5420
toString() {

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

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,44 @@ export default class BinarySearchTreeNode extends BinaryTreeNode {
4747
return !!this.find(value);
4848
}
4949

50+
remove(value) {
51+
const nodeToRemove = this.find(value);
52+
53+
if (!nodeToRemove) {
54+
throw new Error('Item not found in the tree');
55+
}
56+
57+
const { parent } = nodeToRemove;
58+
59+
if (!nodeToRemove.left && !nodeToRemove.right) {
60+
// Node is a leaf and thus has no children.
61+
// Just remove the pointer to this node from the parent node.
62+
parent.removeChild(nodeToRemove);
63+
} else if (nodeToRemove.left && nodeToRemove.right) {
64+
// Node has two children.
65+
// Find the next biggest value (minimum value in the right branch)
66+
// and replace current value node with that next biggest value.
67+
const nextBiggerNode = nodeToRemove.right.findMin();
68+
if (nextBiggerNode !== nodeToRemove.right) {
69+
this.remove(nextBiggerNode.value);
70+
nodeToRemove.value = nextBiggerNode.value;
71+
} else {
72+
// In case if next right value is the next bigger one and it doesn't have left child
73+
// then just replace node that is going to be deleted with the right node.
74+
nodeToRemove.value = nodeToRemove.right.value;
75+
nodeToRemove.right = nodeToRemove.right.right;
76+
}
77+
} else {
78+
// Node has only one child.
79+
// Make this child to be a direct child of current node's parent.
80+
if (nodeToRemove.left) {
81+
parent.replaceChild(nodeToRemove, nodeToRemove.left);
82+
} else {
83+
parent.replaceChild(nodeToRemove, nodeToRemove.right);
84+
}
85+
}
86+
}
87+
5088
findMin() {
5189
if (!this.left) {
5290
return this;

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

Lines changed: 1 addition & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ describe('BinarySearchTree', () => {
3232
expect(bst.contains(40)).toBeFalsy();
3333
});
3434

35-
it('should remove leaf nodes', () => {
35+
it('should remove nodes', () => {
3636
const bst = new BinarySearchTree();
3737

3838
bst.insert(10);
@@ -46,68 +46,4 @@ describe('BinarySearchTree', () => {
4646
bst.remove(20);
4747
expect(bst.toString()).toBe('10');
4848
});
49-
50-
it('should remove nodes with one child', () => {
51-
const bst = new BinarySearchTree();
52-
53-
bst.insert(10);
54-
bst.insert(20);
55-
bst.insert(5);
56-
bst.insert(30);
57-
58-
expect(bst.toString()).toBe('5,10,20,30');
59-
60-
bst.remove(20);
61-
expect(bst.toString()).toBe('5,10,30');
62-
63-
bst.insert(1);
64-
expect(bst.toString()).toBe('1,5,10,30');
65-
66-
bst.remove(5);
67-
expect(bst.toString()).toBe('1,10,30');
68-
});
69-
70-
it('should remove nodes with two children', () => {
71-
const bst = new BinarySearchTree();
72-
73-
bst.insert(10);
74-
bst.insert(20);
75-
bst.insert(5);
76-
bst.insert(30);
77-
bst.insert(15);
78-
bst.insert(25);
79-
80-
expect(bst.toString()).toBe('5,10,15,20,25,30');
81-
expect(bst.root.find(20).left.value).toBe(15);
82-
expect(bst.root.find(20).right.value).toBe(30);
83-
84-
bst.remove(20);
85-
expect(bst.toString()).toBe('5,10,15,25,30');
86-
87-
bst.remove(15);
88-
expect(bst.toString()).toBe('5,10,25,30');
89-
90-
bst.remove(10);
91-
expect(bst.toString()).toBe('5,25,30');
92-
expect(bst.root.value).toBe(25);
93-
94-
bst.remove(25);
95-
expect(bst.toString()).toBe('5,30');
96-
97-
bst.remove(5);
98-
expect(bst.toString()).toBe('30');
99-
});
100-
101-
it('should throw error when trying to remove not existing node', () => {
102-
const bst = new BinarySearchTree();
103-
104-
bst.insert(10);
105-
bst.insert(20);
106-
107-
function removeNotExistingElementFromTree() {
108-
bst.remove(30);
109-
}
110-
111-
expect(removeNotExistingElementFromTree).toThrow();
112-
});
11349
});

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

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,4 +92,83 @@ describe('BinarySearchTreeNode', () => {
9292
expect(node.find(5)).not.toBeNull();
9393
expect(node.find(5).value).toBe(5);
9494
});
95+
96+
it('should remove leaf nodes', () => {
97+
const bstRootNode = new BinarySearchTreeNode();
98+
99+
bstRootNode.insert(10);
100+
bstRootNode.insert(20);
101+
bstRootNode.insert(5);
102+
103+
expect(bstRootNode.toString()).toBe('5,10,20');
104+
105+
bstRootNode.remove(5);
106+
expect(bstRootNode.toString()).toBe('10,20');
107+
bstRootNode.remove(20);
108+
expect(bstRootNode.toString()).toBe('10');
109+
});
110+
111+
it('should remove nodes with one child', () => {
112+
const bstRootNode = new BinarySearchTreeNode();
113+
114+
bstRootNode.insert(10);
115+
bstRootNode.insert(20);
116+
bstRootNode.insert(5);
117+
bstRootNode.insert(30);
118+
119+
expect(bstRootNode.toString()).toBe('5,10,20,30');
120+
121+
bstRootNode.remove(20);
122+
expect(bstRootNode.toString()).toBe('5,10,30');
123+
124+
bstRootNode.insert(1);
125+
expect(bstRootNode.toString()).toBe('1,5,10,30');
126+
127+
bstRootNode.remove(5);
128+
expect(bstRootNode.toString()).toBe('1,10,30');
129+
});
130+
131+
it('should remove nodes with two children', () => {
132+
const bstRootNode = new BinarySearchTreeNode();
133+
134+
bstRootNode.insert(10);
135+
bstRootNode.insert(20);
136+
bstRootNode.insert(5);
137+
bstRootNode.insert(30);
138+
bstRootNode.insert(15);
139+
bstRootNode.insert(25);
140+
141+
expect(bstRootNode.toString()).toBe('5,10,15,20,25,30');
142+
expect(bstRootNode.find(20).left.value).toBe(15);
143+
expect(bstRootNode.find(20).right.value).toBe(30);
144+
145+
bstRootNode.remove(20);
146+
expect(bstRootNode.toString()).toBe('5,10,15,25,30');
147+
148+
bstRootNode.remove(15);
149+
expect(bstRootNode.toString()).toBe('5,10,25,30');
150+
151+
bstRootNode.remove(10);
152+
expect(bstRootNode.toString()).toBe('5,25,30');
153+
expect(bstRootNode.value).toBe(25);
154+
155+
bstRootNode.remove(25);
156+
expect(bstRootNode.toString()).toBe('5,30');
157+
158+
bstRootNode.remove(5);
159+
expect(bstRootNode.toString()).toBe('30');
160+
});
161+
162+
it('should throw error when trying to remove not existing node', () => {
163+
const bstRootNode = new BinarySearchTreeNode();
164+
165+
bstRootNode.insert(10);
166+
bstRootNode.insert(20);
167+
168+
function removeNotExistingElementFromTree() {
169+
bstRootNode.remove(30);
170+
}
171+
172+
expect(removeNotExistingElementFromTree).toThrow();
173+
});
95174
});

0 commit comments

Comments
 (0)
Please sign in to comment.