5
5
*/
6
6
7
7
import { Node } from './node' ;
8
-
9
- export type CompareFunction < K > = ( a : K , b : K ) => number ;
8
+ import { AvlTree as AvlTreeApi , CompareFunction } from '@tyriar/avl-tree' ;
10
9
11
10
/**
12
11
* Represents how balanced a node's left and right children are.
@@ -24,20 +23,19 @@ const enum BalanceState {
24
23
UNBALANCED_LEFT
25
24
}
26
25
27
- export class AvlTree < K , V > {
28
- protected _root : Node < K , V > = null ;
26
+ export class AvlTree < K , V > implements AvlTreeApi < K , V > {
27
+ protected _root : Node < K , V > | null = null ;
29
28
private _size : number = 0 ;
29
+ private _compare : CompareFunction < K > ;
30
30
31
31
/**
32
32
* Creates a new AVL Tree.
33
33
* @param _compare An optional custom compare function.
34
34
*/
35
35
constructor (
36
- private _compare ?: CompareFunction < K >
36
+ compare ?: CompareFunction < K >
37
37
) {
38
- if ( ! _compare ) {
39
- this . _compare = this . _defaultCompare ;
40
- }
38
+ this . _compare = compare ? compare : this . _defaultCompare ;
41
39
}
42
40
43
41
/**
@@ -72,7 +70,7 @@ export class AvlTree<K, V> {
72
70
* @param root The root of the tree to insert in.
73
71
* @return The new tree root.
74
72
*/
75
- private _insert ( key : K , value : V , root : Node < K , V > ) : Node < K , V > {
73
+ private _insert ( key : K , value : V | undefined , root : Node < K , V > | null ) : Node < K , V > {
76
74
// Perform regular BST insertion
77
75
if ( root === null ) {
78
76
return new Node ( key , value ) ;
@@ -93,23 +91,23 @@ export class AvlTree<K, V> {
93
91
const balanceState = this . _getBalanceState ( root ) ;
94
92
95
93
if ( balanceState === BalanceState . UNBALANCED_LEFT ) {
96
- if ( this . _compare ( key , root . left . key ) < 0 ) {
94
+ if ( this . _compare ( key , ( < Node < K , V > > root . left ) . key ) < 0 ) {
97
95
// Left left case
98
96
root = root . rotateRight ( ) ;
99
97
} else {
100
98
// Left right case
101
- root . left = root . left . rotateLeft ( ) ;
99
+ root . left = ( < Node < K , V > > root . left ) . rotateLeft ( ) ;
102
100
return root . rotateRight ( ) ;
103
101
}
104
102
}
105
103
106
104
if ( balanceState === BalanceState . UNBALANCED_RIGHT ) {
107
- if ( this . _compare ( key , root . right . key ) > 0 ) {
105
+ if ( this . _compare ( key , ( < Node < K , V > > root . right ) . key ) > 0 ) {
108
106
// Right right case
109
107
root = root . rotateLeft ( ) ;
110
108
} else {
111
109
// Right left case
112
- root . right = root . right . rotateRight ( ) ;
110
+ root . right = ( < Node < K , V > > root . right ) . rotateRight ( ) ;
113
111
return root . rotateLeft ( ) ;
114
112
}
115
113
}
@@ -132,7 +130,7 @@ export class AvlTree<K, V> {
132
130
* @param root The root of the tree to delete from.
133
131
* @return The new tree root.
134
132
*/
135
- private _delete ( key : K , root : Node < K , V > ) : Node < K , V > {
133
+ private _delete ( key : K , root : Node < K , V > | null ) : Node < K , V > | null {
136
134
// Perform regular BST deletion
137
135
if ( root === null ) {
138
136
this . _size ++ ;
@@ -155,7 +153,7 @@ export class AvlTree<K, V> {
155
153
root = root . left ;
156
154
} else {
157
155
// Node has 2 children, get the in-order successor
158
- const inOrderSuccessor = this . _minValueNode ( root . right ) ;
156
+ const inOrderSuccessor = this . _minValueNode ( < Node < K , V > > root . right ) ;
159
157
root . key = inOrderSuccessor . key ;
160
158
root . value = inOrderSuccessor . value ;
161
159
root . right = this . _delete ( inOrderSuccessor . key , root . right ) ;
@@ -172,25 +170,25 @@ export class AvlTree<K, V> {
172
170
173
171
if ( balanceState === BalanceState . UNBALANCED_LEFT ) {
174
172
// Left left case
175
- if ( this . _getBalanceState ( root . left ) === BalanceState . BALANCED ||
176
- this . _getBalanceState ( root . left ) === BalanceState . SLIGHTLY_UNBALANCED_LEFT ) {
173
+ if ( this . _getBalanceState ( ( < Node < K , V > > root . left ) ) === BalanceState . BALANCED ||
174
+ this . _getBalanceState ( ( < Node < K , V > > root . left ) ) === BalanceState . SLIGHTLY_UNBALANCED_LEFT ) {
177
175
return root . rotateRight ( ) ;
178
176
}
179
177
// Left right case
180
178
// this._getBalanceState(root.left) === BalanceState.SLIGHTLY_UNBALANCED_RIGHT
181
- root . left = root . left . rotateLeft ( ) ;
179
+ root . left = ( < Node < K , V > > root . left ) . rotateLeft ( ) ;
182
180
return root . rotateRight ( ) ;
183
181
}
184
182
185
183
if ( balanceState === BalanceState . UNBALANCED_RIGHT ) {
186
184
// Right right case
187
- if ( this . _getBalanceState ( root . right ) === BalanceState . BALANCED ||
188
- this . _getBalanceState ( root . right ) === BalanceState . SLIGHTLY_UNBALANCED_RIGHT ) {
185
+ if ( this . _getBalanceState ( ( < Node < K , V > > root . right ) ) === BalanceState . BALANCED ||
186
+ this . _getBalanceState ( ( < Node < K , V > > root . right ) ) === BalanceState . SLIGHTLY_UNBALANCED_RIGHT ) {
189
187
return root . rotateLeft ( ) ;
190
188
}
191
189
// Right left case
192
190
// this._getBalanceState(root.right) === BalanceState.SLIGHTLY_UNBALANCED_LEFT
193
- root . right = root . right . rotateRight ( ) ;
191
+ root . right = ( < Node < K , V > > root . right ) . rotateRight ( ) ;
194
192
return root . rotateLeft ( ) ;
195
193
}
196
194
@@ -200,14 +198,20 @@ export class AvlTree<K, V> {
200
198
/**
201
199
* Gets the value of a node within the tree with a specific key.
202
200
* @param key The key being searched for.
203
- * @return The value of the node or null if it doesn't exist.
201
+ * @return The value of the node (which may be undefined), or null if it
202
+ * doesn't exist.
204
203
*/
205
- public get ( key : K ) : V {
204
+ public get ( key : K ) : V | undefined | null {
206
205
if ( this . _root === null ) {
207
206
return null ;
208
207
}
209
208
210
- return this . _get ( key , this . _root ) . value ;
209
+ const result = this . _get ( key , this . _root ) ;
210
+ if ( result === null ) {
211
+ return null ;
212
+ }
213
+
214
+ return result . value ;
211
215
}
212
216
213
217
/**
@@ -216,7 +220,7 @@ export class AvlTree<K, V> {
216
220
* @param root The root of the tree to search in.
217
221
* @return The value of the node or null if it doesn't exist.
218
222
*/
219
- private _get ( key : K , root : Node < K , V > ) : Node < K , V > {
223
+ private _get ( key : K , root : Node < K , V > ) : Node < K , V > | null {
220
224
const result = this . _compare ( key , root . key ) ;
221
225
if ( result === 0 ) {
222
226
return root ;
@@ -249,16 +253,22 @@ export class AvlTree<K, V> {
249
253
}
250
254
251
255
/**
252
- * @return The minimum key in the tree.
256
+ * @return The minimum key in the tree or null if there are no nodes .
253
257
*/
254
- public findMinimum ( ) : K {
258
+ public findMinimum ( ) : K | null {
259
+ if ( this . _root === null ) {
260
+ return null ;
261
+ }
255
262
return this . _minValueNode ( this . _root ) . key ;
256
263
}
257
264
258
265
/**
259
- * Gets the maximum key in the tree.
266
+ * Gets the maximum key in the tree or null if there are no nodes .
260
267
*/
261
- public findMaximum ( ) : K {
268
+ public findMaximum ( ) : K | null {
269
+ if ( this . _root === null ) {
270
+ return null ;
271
+ }
262
272
return this . _maxValueNode ( this . _root ) . key ;
263
273
}
264
274
0 commit comments