Skip to content

Commit da6fe2d

Browse files
Completed BST remove method (Closes CoffeelessProgrammer#7)
BinarySearchTree implementation requires testing. Updated repo READMEs. Trees section of course complete.
1 parent 8140630 commit da6fe2d

File tree

7 files changed

+188
-41
lines changed

7 files changed

+188
-41
lines changed

Data-Structures/README.md

+13-8
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66
- [ ] Stacks
77
- [ ] Queues
88
- [ ] Linked Lists
9-
- [ ] Trees
10-
- [ ] Binary Search Tree (BST)
11-
- AVL Tree
12-
- Red Black Tree
9+
- [X] Trees
10+
- [X] Binary Search Tree (BST)
11+
- AVL Tree
12+
- Red Black Tree
1313
- Binary Heap
1414
- Priority Queue
1515
- Trie
@@ -18,12 +18,17 @@
1818
## Resources
1919
- [The Data Structures Handbook](https://www.thedshandbook.com/ "DS Handbook")
2020
- [Comprehensive List of Data Structures](https://en.wikipedia.org/wiki/List_of_data_structures "Wikipedia: DS List")
21+
- [Visualizing Data Structures & Algorithms](https://visualgo.net/en)
22+
23+
### Trees
24+
- [BST: VisuAlgo](https://visualgo.net/bn/bst?slide=1)
25+
- [Binary Heap: VisuAlgo](https://visualgo.net/en/heap)
26+
- [AVL Tree Visualization](https://www.cs.usfca.edu/~galles/visualization/AVLtree.html)
27+
- [Red-Black Tree Visualization](https://www.cs.usfca.edu/~galles/visualization/RedBlack.html)
28+
- [Priority Queue Implementation: GeeksForGeeks](https://www.cs.usfca.edu/~galles/visualization/RedBlack.html)
2129

2230
### Hash Tables
2331
- [MD5 Hash Generator](http://www.miraclesalad.com/webtools/md5.php)
2432
- [Hash Table Animation](https://www.cs.usfca.edu/~galles/visualization/OpenHash.html)
2533
- [Hash Table | Wikipedia](https://en.wikipedia.org/wiki/Hash_table)
26-
- [Associative Arrays | Wikipedia](https://en.wikipedia.org/wiki/Comparison_of_programming_languages_(associative_array) "Hash Tables (aka Associative Arrays)")
27-
28-
### Trees
29-
- [BST: VisuAlgo](https://visualgo.net/bn/bst?slide=1)
34+
- [Associative Arrays | Wikipedia](https://en.wikipedia.org/wiki/Comparison_of_programming_languages_(associative_array) "Hash Tables (aka Associative Arrays)")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { assertEquals, assertNotEquals } from '../../test_deps.ts';
2+
3+
import BinarySearchTree from './BinarySearchTree.ts';
4+
5+
6+
//---------------------------------------------------------------------
7+
// ---------- UNIT TESTS ----------
8+
//---------------------------------------------------------------------
9+
10+
// RUN: deno test Data-Structures/Trees/BinarySearchTree.test.ts
11+
12+
Deno.test({
13+
name: "Compare Trees 1",
14+
fn() {
15+
16+
const tree1 = new BinarySearchTree();
17+
tree1.insert(30);
18+
tree1.insert(6);
19+
tree1.insert(92)
20+
const tree2 = new BinarySearchTree();
21+
tree2.insert(30);
22+
tree2.insert(92);
23+
tree2.insert(6);
24+
25+
assertEquals(tree1.equalsQuantum(tree2), true);
26+
}
27+
})
28+
29+
Deno.test({
30+
name: "Compare Trees 2",
31+
fn() {
32+
33+
const tree1 = new BinarySearchTree();
34+
tree1.insert(30);
35+
tree1.insert(6);
36+
tree1.insert(92)
37+
const tree2 = new BinarySearchTree();
38+
tree2.insert(30);
39+
tree2.insert(6);
40+
tree2.insert(91);
41+
42+
assertEquals(tree1.equalsQuantum(tree2), false);
43+
}
44+
})

Data-Structures/Trees/BinarySearchTree.ts

+109-16
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ export default class BinarySearchTree {
4747
}
4848
}
4949

50-
public lookup(value: number) {
50+
public lookup(value: number): BNode | null {
5151
let currentNode: BNode;
5252

5353
if(!!this.root) {
@@ -63,28 +63,125 @@ export default class BinarySearchTree {
6363
}
6464

6565

66-
if (value < currentNode.getValue()) { // Value is smaller than current node
66+
if (value < currentNode.getValue()) { // Value is smaller than current node
6767
if(!!currentNode.getLeft()) { // If left child exists
68-
currentNode = currentNode.getLeft(); // Move into left child
68+
currentNode = currentNode.getLeft(); // Move into left child
6969
continue;
7070
}
71-
return null; // No left child, value DNE
72-
} else { // Value is greater than current node
71+
return null; // Otherwise No left child, value DNE
72+
}
73+
else { // Value is greater than current node
7374
if(!!currentNode.getRight()) { // If right child exists
74-
currentNode = currentNode.getRight(); // Move into right child
75+
currentNode = currentNode.getRight(); // Move into right child
7576
continue;
7677
}
77-
return null; // No right child, value DNE
78+
return null; // Otherwise no right child, value DNE
7879
}
7980
}
8081
}
8182

82-
public remove(value: number) {
83-
// TODO: Remove from node from BST
84-
console.log("Remove not implemented");
83+
public remove(value: number): boolean {
84+
let parentNode: BNode | null;
85+
let currentNode: BNode;
86+
87+
if(!!this.root) {
88+
currentNode = this.root;
89+
parentNode = null;
90+
} else {
91+
return false;
92+
}
93+
94+
while(true) {
95+
96+
if (value < currentNode.getValue()) {
97+
parentNode = currentNode;
98+
currentNode = currentNode.getLeft()
99+
continue;
100+
}
101+
else if(value > currentNode.getValue()) {
102+
parentNode = currentNode;
103+
currentNode = currentNode.getRight();
104+
continue;
105+
}
106+
else if(value === currentNode.getValue()){ // Found node to delete!
107+
// Decision Tree for Deleting a Node
108+
// Branch 1: No right child
109+
if (!currentNode.getRight()) {
110+
if (!parentNode) {
111+
this.root = currentNode.getLeft();
112+
}
113+
else {
114+
115+
if (currentNode.getValue() < parentNode.getValue()) {
116+
parentNode.setLeft(currentNode.getLeft());
117+
}
118+
else if (currentNode.getValue() > parentNode.getValue()) {
119+
parentNode.setRight(currentNode.getLeft());
120+
}
121+
122+
}
123+
}
124+
// Branch 2: Right child w/ no left child
125+
else if (!currentNode.getRight().getLeft()) {
126+
if (!parentNode) {
127+
this.root = currentNode.getLeft();
128+
} else {
129+
currentNode.getRight().setLeft(currentNode.getLeft());
130+
131+
if (currentNode.getValue() < parentNode.getValue()) {
132+
parentNode.setLeft(currentNode.getRight());
133+
}
134+
else if (currentNode.getValue() > parentNode.getValue()) {
135+
parentNode.setRight(currentNode.getRight());
136+
}
137+
}
138+
}
139+
// Branch 3: Right child w/ left child
140+
else {
141+
142+
// Find the right child's left most child
143+
let leftmost = currentNode.getRight().getLeft();
144+
let parentOfLeftmost = currentNode.getRight();
145+
while(!!leftmost.getLeft()) {
146+
parentOfLeftmost = leftmost;
147+
leftmost = leftmost.getLeft();
148+
}
149+
150+
// Parent's left subtree is now leftmost's right subtree
151+
parentOfLeftmost.setLeft(leftmost.getRight());
152+
leftmost.setLeft(currentNode.getLeft());
153+
leftmost.setRight(currentNode.getRight());
154+
155+
if (!parentNode) {
156+
this.root = leftmost;
157+
}
158+
else {
159+
160+
if (currentNode.getValue() < parentNode.getValue()) {
161+
parentNode.setLeft(leftmost);
162+
}
163+
else if (currentNode.getValue() > parentNode.getValue()) {
164+
parentNode.setRight(leftmost);
165+
}
166+
167+
}
168+
}
169+
}
170+
171+
return true; // Node removal was a success!
172+
}
173+
}
174+
175+
public equalsQuantum(tree: BinarySearchTree): boolean {
176+
return JSON.stringify(this) === JSON.stringify(tree);
85177
}
86178
}
87179

180+
function printNode(tree: BinarySearchTree, value: number): void {
181+
const requestedNode = tree.lookup(value);
182+
console.log('Find', value + ':', !!requestedNode ? JSON.stringify(requestedNode) : 'Node not found.');
183+
}
184+
88185
function traverseFrom(node: BNode | null) {
89186
if(node === null) return;
90187

@@ -104,7 +201,7 @@ if (import.meta.main) {
104201

105202
// 9
106203
// 4 20
107-
// 1 6 15 170
204+
// 1 6 15 170
108205

109206
tree.insert(9);
110207
tree.insert(4);
@@ -114,15 +211,11 @@ if (import.meta.main) {
114211
tree.insert(15);
115212
tree.insert(1);
116213
console.log('Tree: ', JSON.stringify(traverseFrom(tree.getRoot())));
214+
tree.remove(20);
117215
printNode(tree, 4);
118216
printNode(tree, 17);
119217
printNode(tree, 40);
120218
printNode(tree, 170);
121219

122220
// RUN: deno run Data-Structures/Trees/BinarySearchTree.ts
123-
}
124-
125-
function printNode(tree: BinarySearchTree, value: number): void {
126-
const requestedNode = tree.lookup(value);
127-
console.log('Find', value + ':', !!requestedNode ? JSON.stringify(requestedNode) : 'Node not found.');
128221
}

Data-Structures/Trees/BinaryTreeNode.ts

+9-9
Original file line numberDiff line numberDiff line change
@@ -4,32 +4,32 @@ export default class BinaryTreeNode {
44
private right: BinaryTreeNode | null;
55

66
constructor(value: number) {
7+
this.value = value;
78
this.left = null;
89
this.right = null;
9-
this.value = value;
1010
}
1111

1212
public setValue(value: number) {
1313
this.value = value;
1414
}
1515

16-
public setRight(binaryTreeNode: BinaryTreeNode) {
17-
this.right = binaryTreeNode;
18-
}
19-
2016
public setLeft(binaryTreeNode: BinaryTreeNode) {
2117
this.left = binaryTreeNode;
2218
}
2319

24-
public getValue(): number {
25-
return this.value;
20+
public setRight(binaryTreeNode: BinaryTreeNode) {
21+
this.right = binaryTreeNode;
2622
}
2723

28-
public getRight(): BinaryTreeNode | any {
29-
return this.right;
24+
public getValue(): number {
25+
return this.value;
3026
}
3127

3228
public getLeft(): BinaryTreeNode | any {
3329
return this.left;
3430
}
31+
32+
public getRight(): BinaryTreeNode | any {
33+
return this.right;
34+
}
3535
}

Playground/Challenges/Arrays/Compare_Arrays.test.ts

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ const array3 = ['z', 't', 'i'];
1010
// ---------- UNIT TESTS ----------
1111
//---------------------------------------------------------------------
1212

13+
// RUN: deno test Playground/Challenges/Arrays/Compare_Arrays.test.ts
14+
1315
Deno.test({
1416
name: "Matching Elements 1",
1517
fn() {

Playground/Challenges/Hash-Tables/Recurring_Symbol.test.ts

+7-5
Original file line numberDiff line numberDiff line change
@@ -15,42 +15,44 @@ const array5 = ["a", "z", "n", "z", "x", "g"];
1515
// ---------- UNIT TESTS ----------
1616
//---------------------------------------------------------------------
1717

18+
// RUN: deno test Playground/Challenges/Hash-Tables/Recurring_Symbol.test.ts
19+
1820
Deno.test({
1921
name: "Recurring Character",
2022
fn() {
2123
// ["a", "z", "n", "z", "x", "g"];
2224
assertEquals(findFirstRecurring(array5), "z");
23-
},
25+
}
2426
});
2527

2628
Deno.test({
2729
name: "Recurring Number 1",
2830
fn() {
2931
// [2, 5, 1, 2, 3, 5, 1, 2, 4]
3032
assertEquals(firstRecurringNumber(array1), 2);
31-
},
33+
}
3234
});
3335

3436
Deno.test({
3537
name: "Recurring Number 2",
3638
fn() {
3739
// [2, 1, 1, 2, 3, 5, 1, 2, 4]
3840
assertEquals(firstRecurringNumber(array2), 1);
39-
},
41+
}
4042
});
4143

4244
Deno.test({
4345
name: "Recurring Number 3",
4446
fn() {
4547
// [2, 3, 4, 5]
4648
assertEquals(firstRecurringNumber(array3), undefined);
47-
},
49+
}
4850
});
4951

5052
Deno.test({
5153
name: "Recurring Number 4",
5254
fn() {
5355
// [2, 5, 5, 2, 3, 5, 1, 2, 4]
5456
assertEquals(firstRecurringNumber(array4), 5);
55-
},
57+
}
5658
});

README.md

+4-3
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
- [ ] Stacks
1414
- [ ] Queues
1515
- [ ] Linked Lists
16-
- [ ] Trees
16+
- [X] Trees
1717
- [ ] Graphs
1818

1919
### Algorithms
@@ -33,6 +33,7 @@
3333
- TypeScript 3.9.2
3434

3535
## Resources
36-
- [Data Structures & Algorithms: Course Overview](https://coggle.it/diagram/W5E5tqYlrXvFJPsq/t/master-the-interview-click-here-for-course-link "Course and Mindmap by Andrei Neagoie")
3736
- [Comprehensive List of Data Structures](https://en.wikipedia.org/wiki/List_of_data_structures "Wikipedia: DS List")
38-
- [The Big-O Algorithm Complexity Cheat Sheet](https://www.bigocheatsheet.com/ "Big O Cheat Sheet")
37+
- [Visualizing Data Structures & Algorithms](https://visualgo.net/en)
38+
- [The Big-O Algorithm Complexity Cheat Sheet](https://www.bigocheatsheet.com/ "Big O Cheat Sheet")
39+
- [Roadmap: Core Data Structures & Algorithms](https://coggle.it/diagram/W5E5tqYlrXvFJPsq/t/master-the-interview-click-here-for-course-link "Course and Mindmap by Andrei Neagoie")

0 commit comments

Comments
 (0)