-
Notifications
You must be signed in to change notification settings - Fork 312
/
BinarySearchTree.ts
163 lines (136 loc) · 3.61 KB
/
BinarySearchTree.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
import BinaryTreeNode from './BinaryTreeNode';
import BinaryTree from './BinaryTree';
class BinarySearchTree extends BinaryTree<number> {
/**
* Recursively insert a new value in the BST.
* @param {number} value The value being inserted
*/
insert(val: number): void {
this.root = this._insertImpl(val, this.root);
}
/**
* Recursively search for a value in the BST
* @param {number} value The value to search for.
* @param {*} node The current node.
* @return {Boolean} True if value is found, false if not.
*/
search(val: number): boolean {
function searchImpl(
value: number,
node: BinaryTreeNode<number> | null,
): boolean {
if (!node) {
return false;
}
const nodeValue = node.value;
if (nodeValue === value) {
return true;
}
if (value > nodeValue) {
return searchImpl(value, node.right);
}
return searchImpl(value, node.left);
}
return searchImpl(val, this.root);
}
protected _insertImpl(
value: number,
node: BinaryTreeNode<number> | null,
): BinaryTreeNode<number> {
if (!node) {
return new BinaryTreeNode(value);
}
// Normal BST insert
// NOTE: Duplicates are sent to the left
if (value <= node.value) {
node.left = this._insertImpl(value, node.left);
} else {
node.right = this._insertImpl(value, node.right);
}
return node;
}
private _getMinimumNode(
node: BinaryTreeNode<number> | null,
): BinaryTreeNode<number> | null {
if (!node) {
return null;
}
const { left } = node;
if (!left) {
return node;
}
return this._getMinimumNode(left);
}
/**
* Recursively get the minimum value in the tree.
* @param {BinaryTreeNode} node The current node. Param is not required.
* @return {*} The minimum value.
*/
getMinimum(): number | null {
const minNode = this._getMinimumNode(this.root);
return minNode != null ? minNode.value : null;
}
/**
* Recursively get the maximum value in the tree.
* @return {*} The maximum value.
*/
getMaximum(): number | null {
function getMaximumImpl(
node: BinaryTreeNode<number> | null,
): number | null {
if (!node) {
return null;
}
const { right } = node;
if (!right) {
return node.value;
}
return getMaximumImpl(right);
}
return getMaximumImpl(this.root);
}
/**
* Recursively delete a given value from the tree.
* @param {number} value The value to delete.
* @param {BinaryTreeNode} node The current node.
* @return {BinaryTreeNode} The root node after deletion.
*/
delete(val: number): BinaryTreeNode<number> | null {
this.root = this._deleteImpl(val, this.root);
return this.root;
}
protected _deleteImpl(
value: number,
node: BinaryTreeNode<number> | null,
): BinaryTreeNode<number> | null {
if (!node) {
return null;
}
const nodeValue = node.value;
const { left } = node;
const { right } = node;
if (value < nodeValue) {
node.left = this._deleteImpl(value, left);
return node;
} else if (value > nodeValue) {
node.right = this._deleteImpl(value, right);
return node;
}
if (!left && !right) {
return null;
}
if (!left) {
return right;
}
if (!right) {
return left;
}
const tempNode: BinaryTreeNode<number> = this._getMinimumNode(
right,
) as BinaryTreeNode<number>;
node.value = tempNode.value;
node.right = this._deleteImpl(tempNode.value, right);
return node;
}
}
export default BinarySearchTree;