Skip to content

Commit c791ba2

Browse files
committedOct 7, 2018
docs for bst
1 parent dfd3f93 commit c791ba2

13 files changed

+323
-46
lines changed
 

‎book/chapters/array.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,6 @@ To sum up, the time complexity on an array is:
177177
.Time complexity for the array operations
178178
|===
179179
.2+.^s| Data Structure 2+^s| Searching By 3+^s| Inserting at the 3+^s| Deleting from .2+.^s| Space Complexity
180-
|_Index/Key_ |_Value_ |_beginning_ |_middle_ |_end_ |_beginning_ |_middle_ |_end_
180+
^|_Index/Key_ ^|_Value_ ^|_beginning_ ^|_middle_ ^|_end_ ^|_beginning_ ^|_middle_ ^|_end_
181181
| Array ^|O(1) ^|O(n) ^|O(n) ^|O(n) ^|O(1) ^|O(n) ^|O(n) ^|O(1) ^|O(n)
182182
|===

‎book/chapters/binary-search-tree.adoc

Lines changed: 170 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,172 @@
11
= Binary Search Tree
22

3-
Laboris ut sint id veniam sunt adipisicing sit et laborum. Aliquip exercitation non pariatur duis fugiat elit ullamco reprehenderit tempor. Nostrud ut commodo eu eiusmod. Veniam sit sunt elit ex elit minim cillum magna dolore. Tempor ex cupidatat esse in aliqua duis irure qui magna mollit id occaecat.
3+
.The Binary Search Tree (BST) is a binary tree that keeps the following constaints:
4+
* Each node must have at most 2 children. Usually referred as left and right.
5+
* All trees must a have a root node.
6+
* Nodes values must be ordered after each insert/delete operation.
7+
* The order of nodes values must be: left child < parent < right child.
8+
9+
== Implementing a Binary Search Tree
10+
11+
The first step is to implement the TreeNode:
12+
13+
.Binary Tree Node's constructor
14+
[source, javascript]
15+
----
16+
include::{codedir}/data-structures/trees/binary-tree-node.js[tag=snippet, indent=0]
17+
----
18+
19+
Does this look familiar to you? It’s almost like the linked list node, but instead of having next and previous, it has left and right. That guarantees that we have at most two children.
20+
21+
We also added the meta object to hold some metadata about the node, like duplicity, color (for red-black trees), or any other data needed for future algorithms.
22+
23+
We implemented the node, now let’s go with the tree:
24+
25+
.Binary Search Tree's class
26+
[source, javascript]
27+
----
28+
include::{codedir}/data-structures/trees/binary-search-tree.js[tag=snippet, indent=0]
29+
30+
add(value) { /* ... */ }
31+
find(value) { /* ... */ }
32+
remove(value) { /* ... */ }
33+
getMax() { /* ... */ }
34+
getMin() { /* ... */ }
35+
}
36+
----
37+
38+
This guarantees that our trees have one root element from where we can navigate left or right based on the value that we are looking for. We have placeholders for the operations that we are going to implement in a moment.
39+
40+
=== Inserting new elements in a BST
41+
42+
.For inserting an element in a BST we have two scenarios:
43+
1. If tree is empty (root element is null), we add the newly created node as a root and we are done!
44+
2. Starting from the root, compare the node’s value against the new element. If node has higher than new element, we move to the right child, otherwise to the left. We check recursively each node until we find an empty spot where we can put the new element and keep the rule right < parent < left.
45+
3. If we insert the same value multiple times, we don’t want duplicates. So, we can keep track using a duplicity counter.
46+
47+
For instance, let’s say that we want to insert the values 19,21,10,2,8 in a BST:
48+
49+
.Inserting values on a BST.
50+
image:image36.png[image,width=528,height=329]
51+
52+
53+
In the last box, when we are inserting node 18, we start by the root (19). Since 18 is less than 19, then we move left. Node 18 is greater than 10, so we move right. There’s an empty spot and we place it there. Let’s code it up:
54+
55+
.Binary Search Tree's class
56+
[source, javascript]
57+
----
58+
include::{codedir}/data-structures/trees/binary-search-tree.js[tag=add, indent=0]
59+
----
60+
<1> We are using a helper function `findNodeAndParent` to iterate through the tree finding a node with current value “found” and its parent.
61+
<2> We are taking care of duplicates. Instead of inserting duplicates we are keeping a multiplicity tally. We have to decrease it when removing nodes.
62+
63+
=== Finding a value in a BST
64+
65+
We can implement the find method using the helper `findNodeAndParent` as follows:
66+
67+
.Binary Search Tree's find methods
68+
[source, javascript]
69+
----
70+
include::{codedir}/data-structures/trees/binary-search-tree.js[tag=find, indent=0]
71+
----
72+
73+
`findNodeAndParent` is a recursive function that goes to the left child or right depending on the value. However, if the value already exists, it will return it in `found` variable.
74+
75+
=== Removing elements from a BST
76+
77+
Deleting a node from a BST have three cases.
78+
79+
.The node is a
80+
1. leaf
81+
2. parent with one child
82+
3. parent with two children/root.
83+
84+
==== Removing a leaf (Node with 0 children)
85+
86+
Deleting a leaf is the easiest, we just look for their parent and set the child to null.
87+
88+
.Removing node without children from a BST.
89+
image:image37.png[image,width=528,height=200]
90+
91+
92+
Node 18, will be hanging around until the garbage collector is run. However, there’s no node referencing to it so it won’t be reachable from the tree anymore.
93+
94+
==== Removing a parent (Node with 1 children)
95+
96+
Removing a parent is not as easy, since you need to find new parents for its children.
97+
98+
.Removing node with 1 children from a BST.
99+
image:image38.png[image,width=528,height=192]
100+
101+
102+
In the example, we removed node 10 from the tree so its child (node 2) needs a new parent. We made node 19 the new parent for node 2.
103+
104+
==== Removing a full parent (Node with 2 children) or root
105+
106+
This is the trickiest of all cases because we need to find new parents for two children.
107+
108+
.Removing node with two children from a BST.
109+
image:image39.png[image,width=528,height=404]
110+
111+
112+
In the example, we delete the root node 19. This leaves the two orphans (node 10 and node 21). There’s no more parents because node 19 was the *root* element. One way to solve this problem, is to *combine* the left subtree (Node 10 and descendants) into the right subtree (node 21). The final result is node 21 is the new root.
113+
114+
What would happen if node 21 had a left child (e.g. node 20)? Well, we would move node 10 and its descendants bellow node 20.
115+
116+
==== Implementing removing elements from a BST
117+
118+
All the described scenarios removing nodes with 0, 1 and 2 children can be sum up on this code:
119+
120+
.Binary Search Tree's remove method
121+
[source, javascript]
122+
----
123+
include::{codedir}/data-structures/trees/binary-search-tree.js[tag=remove, indent=0]
124+
----
125+
<1> Try to find if value exists on the tree.
126+
<2> If value doesn’t exist we are done!
127+
<3> Create new subtree without the value to delete
128+
<4> Check the multiplicity (duplicates) and decrement the count in case we have multiple nodes with the same value
129+
<5> If the `nodeToRemove` was the root, then we move the removed node’s children as the new root.
130+
<6> If it was not the root, then we go to the deleted node’s parent and put their children there.
131+
132+
133+
We compute `removedNodeChildren`, which is the resulting subtree after combining the children of the deleted node.
134+
135+
The method to combine subtrees is the following:
136+
137+
.Binary Search Tree's combine method
138+
[source, javascript]
139+
----
140+
include::{codedir}/data-structures/trees/binary-search-tree.js[tag=combine, indent=0]
141+
----
142+
143+
Take a look at code above and the example. You will see how to remove node 30 and combine both children subtree and keeping the BST rules. Also, this method uses a helper to get the left-most node. We can implement it like this:
144+
145+
.Binary Search Tree's get left most method
146+
[source, javascript]
147+
----
148+
include::{codedir}/data-structures/trees/binary-search-tree.js[tag=leftMost, indent=0]
149+
----
150+
151+
That’s all we need to remove elements from a BST. Check out the complete BST implementation at: https://github.com/amejiarosario/algorithms.js/blob/master/src/data-structures/trees/binary-search-tree.js
152+
153+
== Differentiating a balanced and non-balanced Tree
154+
155+
As we insert and remove nodes from a BST we could ended up like the tree on the left:
156+
157+
.Balanced vs Unbalanced Tree.
158+
image:image40.png[image,width=454,height=201]
159+
160+
The tree on the left is unbalanced. It actually looks like a Linked List and has the same runtime! Searching for an element would be *O(n)*. However, on a balanced tree the search time is *O(log n)*. That’s why we always want to keep the tree balanced. In further chapters, we are going to explore how to keep a tree balanced after each insert/delete.
161+
162+
== Tree Complexity
163+
164+
We can sum up the tree operations using Big O notation:
165+
166+
.Time complexity for a Binary Search Tree (BST)
167+
|===
168+
.2+.^s| Data Structure 2+^s| Searching By .2+^.^s| Insert .2+^.^s| Delete .2+^.^s| Space Complexity
169+
^|_Index/Key_ ^|_Value_
170+
| BST (**un**balanced) ^|- ^|O(n) ^|O(n) ^|O(n) ^|O(n)
171+
| BST (balanced) ^|- ^|O(log n) ^|O(log n) ^|O(log n) ^|O(n)
172+
|===

‎book/chapters/graph.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
= Graph
22

3-
Aliqua non cillum quis ipsum tempor eiusmod. Cillum reprehenderit occaecat in veniam. Est anim proident duis reprehenderit sit nisi aute laborum esse quis consectetur id consectetur. Laborum occaecat consequat exercitation culpa sunt et aliqua voluptate anim.
3+
Non-linear data structure organize data differently. Instead of one data point leading to the next one, it would lead to many others forming graphs and trees.
44

55
== Depth First Search
66

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,20 @@
11
[partintro]
22
--
3-
Data Structures comes in many flavors. There’s no one to rule them all. There are tradeoffs for each one of them. Even thought in your day-to-day work, you might not need to re-implementing them. However, knowing how they work internally would help to know when to use one over another. We are going to explore the most common data structures time and space complexity.
3+
Data Structures comes in many flavors. There’s no one to rule them all. There are tradeoffs for each one of them. Even thought in your day-to-day work, you might not need to re-implementing them. However, knowing how they work internally would help to choose one over another depending on your needs. We are going to explore the most common data structures time and space complexity.
44

5-
.In this chapter we are going to learn about the following linear data structures:
5+
.In this part we are going to learn about the following linear data structures:
66
- Array
77
- Linked List
88
- Stack
99
- Queue
10+
11+
Later, in the 2nd part we are going to explore non-linear data structures like Graphs and Trees.
12+
ifdef::backend-html5[]
13+
If you want to have a general overview of each one, take a look at the following interactive diagram:
14+
+++
15+
<iframe
16+
src="https://embed.kumu.io/85f1a4de5fb8430a10a1bf9c5118e015"
17+
width="940" height="600" frameborder="0"></iframe>
18+
+++
19+
endif::[]
1020
--

‎book/chapters/linked-list.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ So far, we have seen two liner data structures with different use cases. Here’
245245
.Big O cheat sheet for Linked List and Array
246246
|===
247247
.2+.^s| Data Structure 2+^s| Searching By 3+^s| Inserting at the 3+^s| Deleting from .2+.^s| Space Complexity
248-
|_Index/Key_ |_Value_ |_beginning_ |_middle_ |_end_ |_beginning_ |_middle_ |_end_
248+
^|_Index/Key_ ^|_Value_ ^|_beginning_ ^|_middle_ ^|_end_ ^|_beginning_ ^|_middle_ ^|_end_
249249
| Array ^|O(1) ^|O(n) ^|O(n) ^|O(n) ^|O(1) ^|O(n) ^|O(n) ^|O(1) ^|O(n)
250250
| Linked List (singly) ^|O(n) ^|O(n) ^|O(1) ^|O(n) ^|O(1) ^|O(1) ^|O(n) ^|*O(n)* ^|O(n)
251251
| Linked List (doubly) ^|O(n) ^|O(n) ^|O(1) ^|O(n) ^|O(1) ^|O(1) ^|O(n) ^|*O(1)* ^|O(n)

‎book/chapters/map.adoc

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11
= Map
22

3-
Labore ea in excepteur dolore culpa ipsum nostrud reprehenderit excepteur. Tempor qui consectetur minim aliquip dolor amet tempor do duis. Aute dolore fugiat dolore velit proident reprehenderit incididunt minim. Commodo magna cillum laboris esse culpa minim duis laboris proident amet id do nisi laborum. Ut Lorem labore aute ex proident reprehenderit magna veniam est enim elit. Ut minim nulla dolor consequat et ex consequat eiusmod consectetur nostrud aliquip.
3+
A map is a data structure to store pairs of data: *key* and *value*. In an array, you can only store values. The array’s key is always the position index. However, in a *Map* the key can be whatever you want.
4+
5+
Map is a data structure that _maps_ *keys* to *values*.
6+
7+
Many languages have maps already built-in. This is an example in JavaScript/Node:
Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,12 @@
11
[partintro]
22
--
3-
Non-linear data structure organize data differently. Instead of one data point leading to the next one, it would have many others. This is the case for Graphs and Trees.
3+
Non-Linear data structures are everywhere weather we realize it or not. They are used in databases, Web (HTML DOM tree), search algorithms, finding best route to get home and so on. We are going to learn the basic concepts and when to choose one over the other.
44

5-
.In this section we are going to graph-based data structures:
6-
* Graph
7-
* Tree
8-
* Map
9-
* Set
10-
11-
By the end of it, you will know the data structures trade-offs and when to use one over the other.
12-
13-
#Fix description#
14-
15-
This is a general view of how the data structures are related
16-
+++
17-
<iframe
18-
src="https://embed.kumu.io/85f1a4de5fb8430a10a1bf9c5118e015"
19-
width="940" height="600" frameborder="0"></iframe>
20-
+++
5+
.In this chapter we are going to learn:
6+
- Exciting <<Graph>> data structure applications
7+
- Searching efficiently with a <<Tree>> data structures.
8+
- One of the most versatile data structure of all <<HashMaps>>.
9+
- Keeping dups out with a <<Sets>>.
2110
11+
By the end of this section, you will know the data structures trade-offs and when to use one over the other.
2212
--

‎book/chapters/queue.adoc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ A mode of experiment we can see in the following table that if we would have imp
6565
.Time complexity for queue operations
6666
|===
6767
.2+.^s| Data Structure 2+^s| Searching By 3+^s| Inserting at the 3+^s| Deleting from .2+.^s| Space Complexity
68-
|_Index/Key_ |_Value_ |_beginning_ |_middle_ |_end_ |_beginning_ |_middle_ |_end_
68+
^|_Index/Key_ ^|_Value_ ^|_beginning_ ^|_middle_ ^|_end_ ^|_beginning_ ^|_middle_ ^|_end_
6969
| Queue (w/array) ^|- ^|- ^|- ^|- ^|*O(n)* ^|- ^|- ^|O(1) ^|O(n)
7070
| Queue (w/list) ^|- ^|- ^|- ^|- ^|O(1) ^|- ^|- ^|O(1) ^|O(n)
7171
|===
@@ -94,7 +94,7 @@ To sum up,
9494
.Time Complexity of Linear Data Structures (Array, LinkedList, Stack & Queues)
9595
|===
9696
.2+.^s| Data Structure 2+^s| Searching By 3+^s| Inserting at the 3+^s| Deleting from .2+.^s| Space Complexity
97-
|_Index/Key_ |_Value_ |_beginning_ |_middle_ |_end_ |_beginning_ |_middle_ |_end_
97+
^|_Index/Key_ ^|_Value_ ^|_beginning_ ^|_middle_ ^|_end_ ^|_beginning_ ^|_middle_ ^|_end_
9898
| <<Array>> ^|O(1) ^|O(n) ^|O(n) ^|O(n) ^|O(1) ^|O(n) ^|O(n) ^|O(1) ^|O(n)
9999
| <<Singly Linked List>> ^|O(n) ^|O(n) ^|O(1) ^|O(n) ^|O(1) ^|O(1) ^|O(n) ^|*O(n)* ^|O(n)
100100
| <<Doubly Linked List>> ^|O(n) ^|O(n) ^|O(1) ^|O(n) ^|O(1) ^|O(1) ^|O(n) ^|*O(1)* ^|O(n)

‎book/chapters/stack.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ Implementing the stack with an array and linked list would lead to the same time
6767
.Time complexity for the stack operations
6868
|===
6969
.2+.^s| Data Structure 2+^s| Searching By 3+^s| Inserting at the 3+^s| Deleting from .2+.^s| Space Complexity
70-
|_Index/Key_ |_Value_ |_beginning_ |_middle_ |_end_ |_beginning_ |_middle_ |_end_
70+
^|_Index/Key_ ^|_Value_ ^|_beginning_ ^|_middle_ ^|_end_ ^|_beginning_ ^|_middle_ ^|_end_
7171
| Stack ^|- ^|- ^|- ^|- ^|O(1) ^|- ^|- ^|O(1) ^|O(n)
7272
|===
7373

‎book/chapters/tree.adoc

Lines changed: 88 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,90 @@
11
= Tree
22

3-
Elit est quis occaecat exercitation qui duis consectetur ut officia fugiat in ad. Amet qui eiusmod sit ea occaecat. Elit in nisi laborum ullamco quis officia cillum dolor nostrud. Cillum fugiat non velit velit. Aliquip proident aliqua sunt duis fugiat laboris aliqua exercitation aliquip aliquip quis aliqua. Nostrud dolor sint do tempor nostrud cupidatat est.
3+
A tree is a non-linear data structure where node can have zero or more nodes. The first node in a tree is called *root*. The linked nodes to the root is called *children* or *descendants*.
4+
5+
.Tree Data Structure: root node and descendants.
6+
image:image31.jpg[image,width=404,height=240]
7+
8+
They are called “trees” because the data structure resembles a tree . It starts with a *root* node and *branch* off with its descendants, and finally, there are *leaves*.
9+
10+
== Implementing a Tree
11+
12+
Implementing a tree is not that hard. It’s similar to a Linked List but the difference is that instead of having only a next and previous links, we have an array of linked nodes (children).
13+
14+
15+
.Tree's node constructor
16+
[source, javascript]
17+
----
18+
include::{codedir}/data-structures/trees/tree-node.js[tag=snippet]
19+
}
20+
21+
// ... methods goes here ...
22+
}
23+
----
24+
25+
Simple! Right? But there are some constraints that you have to keep at all times.
26+
27+
.Tree data structures constraints
28+
1. *Loops*: You have to be careful to not do a circular loop, otherwise this wouldn’t be a tree but a *graph data structure*! E.g. Node A has B as child, then Node B list Node A as its descendant forming a loop. ‍️
29+
2. *Parents*: A node with more than two parents. If that happens is no longer a tree but a graph.
30+
3. *Root*: a tree must have only one root. Two non-connected parts are not a tree. Graph can have non-connected parts and doesn’t have root.
31+
32+
== Basic concepts
33+
34+
.Here’s summary of the tree basic concepts:
35+
* The top most node is called *root*.
36+
* A node’s immediate linked nodes are called *children*.
37+
* A *leaf* or *terminal node* is a node without any descendent or children.
38+
* A node immediate ancestor is called *parent*. Yeah, like a family tree ‍‍‍ you can have *uncles* and *siblings*, and *grandparents*.
39+
* *Internal nodes* are all nodes except for the leaf nodes and root node.
40+
* The connection/link between nodes is called *edge*.
41+
* The *height of a tree* is the distance, edge count, from the farthest leaf to the root. You can also calculate the *height of a node* counting the edges between them and the farthest leaf. For instance, from the image above:
42+
43+
* Node A, has a height of 3.
44+
* Node G has a height of 1.
45+
* Node I, has a height of 0.
46+
47+
* The *depth* *of a tree* is the distance, edge count, from the root to the farthest leaf.
48+
49+
.Tree anatomy
50+
image:image31.jpg[image]
51+
52+
== Types of Binary Trees
53+
54+
There are different kinds of trees depending on the restrictions. E.g. The trees that have at most two children are called *binary tree*, while trees with at most 3 children are called *Ternary Tree*. Since binary trees are most common we are going to cover them here and ternary tree and others in another chapter.
55+
56+
=== Binary Tree
57+
58+
The binary restricts the nodes to have at most 2 children. Trees in general can have 3, 4, 26 or more, but not binary trees.
59+
60+
.Binary tree has at most 2 children while non-binary trees can have more.
61+
image:image32.png[image,width=321,height=193]
62+
63+
64+
=== Binary Search Tree (BST)
65+
66+
BST has the same restriction as binary tree; each node has at most 2 children. Also, there’s another restriction: the left child’s value has to be less than the parent and the right child’s value has be bigger than the parent.
67+
68+
.BST left < parent < right, while non-BST can be in any order.
69+
image:image33.png[image,width=348,height=189]
70+
71+
72+
=== Binary Heap
73+
74+
The heap is a type of binary tree where the children values are higher (max-heap) than the parent but contrary to the BST the left child doesn’t have to be smaller than the right child.
75+
76+
.Heap vs BST, has max/min value in the root, while BST doesn’t.
77+
image:image34.png[image,width=325,height=176]
78+
79+
80+
For a *max-heap*, the root has the highest value. The heap guarantee as you go down by level the elements on higher levels has bigger values than the element on lower levels. The opposite is true for a *min-heap*. In a min-heap the lowest value is at the root and as you go down the lower levels has higher values than the ones above.
81+
82+
.`max-heap` keeps highest value at the top while min-heap keep the lowest at the root.
83+
image:image35.png[image,width=258,height=169]
84+
85+
86+
.Heap vs Binary Search Tree
87+
****
88+
Heap is better at finding max or min values in constant time *O(1)*, while a balanced BST is good a finding any element in *O(log n)*. Heaps are often used to implement priority queues while BST is used when you need every value sorted.
89+
****
90+

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

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
const TreeNode = require('./tree-node');
22
const Queue = require('../queues/queue');
33
const Stack = require('../stacks/stack');
4-
4+
// tag::snippet[]
55
class BinarySearchTree {
66
constructor() {
77
this.root = null;
88
this.size = 0;
99
}
10+
// end::snippet[]
1011

12+
// tag::add[]
1113
/**
1214
* Insert value on the BST.
1315
* If the value is already in the tree, t
@@ -18,9 +20,9 @@ class BinarySearchTree {
1820
const newNode = new TreeNode(value);
1921

2022
if (this.root) {
21-
const { found, parent } = this.findNodeAndParent(value);
23+
const { found, parent } = this.findNodeAndParent(value); // <1>
2224
if (found) { // duplicated: value already exist on the tree
23-
found.meta.multiplicity = (found.meta.multiplicity || 1) + 1;
25+
found.meta.multiplicity = (found.meta.multiplicity || 1) + 1; // <2>
2426
} else if (value < parent.value) {
2527
parent.left = newNode;
2628
} else {
@@ -33,14 +35,7 @@ class BinarySearchTree {
3335
this.size += 1;
3436
return newNode;
3537
}
36-
37-
/**
38-
* Return node if it found it or undefined if not
39-
* @param {any} value value to find
40-
*/
41-
find(value) {
42-
return this.findNodeAndParent(value).found;
43-
}
38+
// end::add[]
4439

4540
/**
4641
* Find if a node is present or not
@@ -51,11 +46,21 @@ class BinarySearchTree {
5146
return !!this.find(value);
5247
}
5348

49+
// tag::find[]
50+
/**
51+
* @param {any} value value to find
52+
* @returns {any} node if it found it or undefined if not
53+
*/
54+
find(value) {
55+
return this.findNodeAndParent(value).found;
56+
}
57+
58+
5459
/**
5560
* Finds the node matching the value.
5661
* If it doesn't find, it returns the leaf where the new value should be added.
5762
* @param {any} value Node's value to find
58-
* @returns {TreeNode} matching node or the previous node where value should go
63+
* @returns {object} node and its parent like {node, parent}
5964
*/
6065
findNodeAndParent(value, node = this.root, parent = null) {
6166
if (!node || node.value === value) {
@@ -65,6 +70,7 @@ class BinarySearchTree {
6570
}
6671
return this.findNodeAndParent(value, node.right, node);
6772
}
73+
// end::find[]
6874

6975
/**
7076
* Get the node with the max value of subtree: the right-most value.
@@ -78,6 +84,7 @@ class BinarySearchTree {
7884
return this.getMax(node.right);
7985
}
8086

87+
// tag::leftMost[]
8188
/**
8289
* Get the node with the min value of subtree: the left-most value.
8390
* @param {TreeNode} node subtree's root
@@ -89,26 +96,29 @@ class BinarySearchTree {
8996
}
9097
return this.getMin(node.left);
9198
}
99+
// end::leftMost[]
92100

101+
102+
// tag::remove[]
93103
/**
94104
* Remove a node from the tree
95105
* @returns {boolean} false if not found and true if it was deleted
96106
*/
97107
remove(value) {
98-
const { found: nodeToRemove, parent } = this.findNodeAndParent(value);
108+
const { found: nodeToRemove, parent } = this.findNodeAndParent(value); // <1>
99109

100-
if (!nodeToRemove) return false;
110+
if (!nodeToRemove) return false; // <2>
101111

102112
// Combine left and right children into one subtree without nodeToRemove
103-
const removedNodeChildren = this.combineLeftIntoRightSubtree(nodeToRemove);
113+
const removedNodeChildren = this.combineLeftIntoRightSubtree(nodeToRemove); // <3>
104114

105-
if (nodeToRemove.meta.multiplicity && nodeToRemove.meta.multiplicity > 1) {
115+
if (nodeToRemove.meta.multiplicity && nodeToRemove.meta.multiplicity > 1) { // <4>
106116
nodeToRemove.meta.multiplicity -= 1; // handles duplicated
107-
} else if (nodeToRemove === this.root) {
117+
} else if (nodeToRemove === this.root) { // <5>
108118
// Replace (root) node to delete with the combined subtree.
109119
this.root = removedNodeChildren;
110120
if (this.root) { this.root.parent = null; } // clearing up old parent
111-
} else {
121+
} else { // <6>
112122
const side = nodeToRemove.isParentLeftChild ? 'left' : 'right';
113123
// Replace node to delete with the combined subtree.
114124
parent[side] = removedNodeChildren;
@@ -117,7 +127,9 @@ class BinarySearchTree {
117127
this.size -= 1;
118128
return true;
119129
}
130+
// end::remove[]
120131

132+
// tag::combine[]
121133
/**
122134
* Combine left into right children into one subtree without given parent node.
123135
*
@@ -145,6 +157,7 @@ class BinarySearchTree {
145157
}
146158
return node.left;
147159
}
160+
// end::combine[]
148161

149162
/**
150163
* Breath-first search for a tree (always starting from the root element).

‎src/data-structures/trees/binary-tree-node.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// tag::snippet[]
12
/**
23
* Binary Tree Node
34
*/
@@ -8,5 +9,6 @@ class BinaryTreeNode {
89
this.right = null;
910
}
1011
}
12+
// end::snippet[]
1113

1214
module.exports = BinaryTreeNode;

‎src/data-structures/trees/tree-node.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
const LEFT = 0;
22
const RIGHT = 1;
33

4+
// tag::snippet[]
45
class TreeNode {
56
constructor(value) {
67
this.value = value;
78
this.descendents = [];
9+
// end::snippet[]
810
this.parent = null;
911
this.parentSide = null;
1012
this.meta = {};

0 commit comments

Comments
 (0)
Please sign in to comment.