red-black-tree-typed 1.53.7 → 1.54.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +2 -2
- package/README.md +52 -0
- package/dist/common/index.js +5 -0
- package/dist/data-structures/base/iterable-entry-base.js +4 -4
- package/dist/data-structures/binary-tree/avl-tree-counter.d.ts +213 -0
- package/dist/data-structures/binary-tree/avl-tree-counter.js +407 -0
- package/dist/data-structures/binary-tree/avl-tree-multi-map.d.ts +71 -170
- package/dist/data-structures/binary-tree/avl-tree-multi-map.js +133 -328
- package/dist/data-structures/binary-tree/avl-tree.d.ts +103 -69
- package/dist/data-structures/binary-tree/avl-tree.js +130 -70
- package/dist/data-structures/binary-tree/binary-indexed-tree.d.ts +3 -0
- package/dist/data-structures/binary-tree/binary-indexed-tree.js +3 -0
- package/dist/data-structures/binary-tree/binary-tree.d.ts +268 -202
- package/dist/data-structures/binary-tree/binary-tree.js +311 -263
- package/dist/data-structures/binary-tree/bst.d.ts +193 -139
- package/dist/data-structures/binary-tree/bst.js +248 -164
- package/dist/data-structures/binary-tree/index.d.ts +3 -1
- package/dist/data-structures/binary-tree/index.js +3 -1
- package/dist/data-structures/binary-tree/red-black-tree.d.ts +286 -0
- package/dist/data-structures/binary-tree/{rb-tree.js → red-black-tree.js} +176 -107
- package/dist/data-structures/binary-tree/tree-counter.d.ts +212 -0
- package/dist/data-structures/binary-tree/tree-counter.js +444 -0
- package/dist/data-structures/binary-tree/tree-multi-map.d.ts +78 -170
- package/dist/data-structures/binary-tree/tree-multi-map.js +145 -367
- package/dist/data-structures/graph/abstract-graph.js +2 -2
- package/dist/data-structures/graph/directed-graph.d.ts +3 -0
- package/dist/data-structures/graph/directed-graph.js +3 -0
- package/dist/data-structures/graph/map-graph.d.ts +3 -0
- package/dist/data-structures/graph/map-graph.js +3 -0
- package/dist/data-structures/graph/undirected-graph.d.ts +3 -0
- package/dist/data-structures/graph/undirected-graph.js +3 -0
- package/dist/data-structures/hash/hash-map.d.ts +31 -1
- package/dist/data-structures/hash/hash-map.js +35 -5
- package/dist/data-structures/heap/heap.d.ts +20 -3
- package/dist/data-structures/heap/heap.js +31 -11
- package/dist/data-structures/linked-list/doubly-linked-list.d.ts +46 -11
- package/dist/data-structures/linked-list/doubly-linked-list.js +68 -21
- package/dist/data-structures/linked-list/singly-linked-list.d.ts +47 -11
- package/dist/data-structures/linked-list/singly-linked-list.js +73 -26
- package/dist/data-structures/linked-list/skip-linked-list.d.ts +3 -0
- package/dist/data-structures/linked-list/skip-linked-list.js +3 -0
- package/dist/data-structures/matrix/matrix.d.ts +3 -0
- package/dist/data-structures/matrix/matrix.js +3 -0
- package/dist/data-structures/matrix/navigator.d.ts +3 -0
- package/dist/data-structures/matrix/navigator.js +3 -0
- package/dist/data-structures/priority-queue/max-priority-queue.d.ts +3 -0
- package/dist/data-structures/priority-queue/max-priority-queue.js +3 -0
- package/dist/data-structures/priority-queue/min-priority-queue.d.ts +3 -0
- package/dist/data-structures/priority-queue/min-priority-queue.js +3 -0
- package/dist/data-structures/queue/deque.d.ts +37 -8
- package/dist/data-structures/queue/deque.js +73 -29
- package/dist/data-structures/queue/queue.d.ts +41 -1
- package/dist/data-structures/queue/queue.js +51 -9
- package/dist/data-structures/stack/stack.d.ts +27 -10
- package/dist/data-structures/stack/stack.js +39 -20
- package/dist/data-structures/trie/trie.d.ts +8 -7
- package/dist/data-structures/trie/trie.js +8 -7
- package/dist/index.d.ts +4 -4
- package/dist/index.js +4 -4
- package/dist/interfaces/binary-tree.d.ts +8 -8
- package/dist/types/data-structures/base/base.d.ts +1 -1
- package/dist/types/data-structures/binary-tree/avl-tree-counter.d.ts +2 -0
- package/dist/types/data-structures/binary-tree/avl-tree-multi-map.d.ts +1 -4
- package/dist/types/data-structures/binary-tree/avl-tree.d.ts +0 -3
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +0 -3
- package/dist/types/data-structures/binary-tree/bst.d.ts +4 -4
- package/dist/types/data-structures/binary-tree/index.d.ts +3 -1
- package/dist/types/data-structures/binary-tree/index.js +3 -1
- package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +3 -0
- package/dist/types/data-structures/binary-tree/red-black-tree.js +2 -0
- package/dist/types/data-structures/binary-tree/tree-counter.d.ts +2 -0
- package/dist/types/data-structures/binary-tree/tree-counter.js +2 -0
- package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +2 -5
- package/package.json +3 -3
- package/src/common/index.ts +7 -1
- package/src/data-structures/base/iterable-entry-base.ts +4 -4
- package/src/data-structures/binary-tree/avl-tree-counter.ts +463 -0
- package/src/data-structures/binary-tree/avl-tree-multi-map.ts +151 -370
- package/src/data-structures/binary-tree/avl-tree.ts +162 -105
- package/src/data-structures/binary-tree/binary-indexed-tree.ts +3 -0
- package/src/data-structures/binary-tree/binary-tree.ts +488 -416
- package/src/data-structures/binary-tree/bst.ts +326 -251
- package/src/data-structures/binary-tree/index.ts +3 -1
- package/src/data-structures/binary-tree/{rb-tree.ts → red-black-tree.ts} +219 -145
- package/src/data-structures/binary-tree/tree-counter.ts +504 -0
- package/src/data-structures/binary-tree/tree-multi-map.ts +159 -401
- package/src/data-structures/graph/abstract-graph.ts +2 -2
- package/src/data-structures/graph/directed-graph.ts +3 -0
- package/src/data-structures/graph/map-graph.ts +3 -0
- package/src/data-structures/graph/undirected-graph.ts +3 -0
- package/src/data-structures/hash/hash-map.ts +37 -7
- package/src/data-structures/heap/heap.ts +33 -10
- package/src/data-structures/linked-list/doubly-linked-list.ts +75 -21
- package/src/data-structures/linked-list/singly-linked-list.ts +80 -27
- package/src/data-structures/linked-list/skip-linked-list.ts +3 -0
- package/src/data-structures/matrix/matrix.ts +3 -0
- package/src/data-structures/matrix/navigator.ts +3 -0
- package/src/data-structures/priority-queue/max-priority-queue.ts +3 -0
- package/src/data-structures/priority-queue/min-priority-queue.ts +3 -0
- package/src/data-structures/queue/deque.ts +72 -28
- package/src/data-structures/queue/queue.ts +50 -7
- package/src/data-structures/stack/stack.ts +39 -20
- package/src/data-structures/trie/trie.ts +8 -7
- package/src/index.ts +4 -4
- package/src/interfaces/binary-tree.ts +10 -21
- package/src/types/data-structures/base/base.ts +1 -1
- package/src/types/data-structures/binary-tree/avl-tree-counter.ts +3 -0
- package/src/types/data-structures/binary-tree/avl-tree-multi-map.ts +1 -6
- package/src/types/data-structures/binary-tree/avl-tree.ts +0 -5
- package/src/types/data-structures/binary-tree/binary-tree.ts +0 -5
- package/src/types/data-structures/binary-tree/bst.ts +6 -6
- package/src/types/data-structures/binary-tree/index.ts +3 -1
- package/src/types/data-structures/binary-tree/red-black-tree.ts +5 -0
- package/src/types/data-structures/binary-tree/tree-counter.ts +3 -0
- package/src/types/data-structures/binary-tree/tree-multi-map.ts +2 -7
- package/dist/data-structures/binary-tree/rb-tree.d.ts +0 -209
- package/dist/types/data-structures/binary-tree/rb-tree.d.ts +0 -6
- package/src/types/data-structures/binary-tree/rb-tree.ts +0 -10
- /package/dist/types/data-structures/binary-tree/{rb-tree.js → avl-tree-counter.js} +0 -0
|
@@ -6,8 +6,6 @@
|
|
|
6
6
|
* @license MIT License
|
|
7
7
|
*/
|
|
8
8
|
import type {
|
|
9
|
-
BSTNested,
|
|
10
|
-
BSTNodeNested,
|
|
11
9
|
BSTNOptKeyOrNode,
|
|
12
10
|
BSTOptions,
|
|
13
11
|
BTNRep,
|
|
@@ -15,10 +13,12 @@ import type {
|
|
|
15
13
|
Comparator,
|
|
16
14
|
CP,
|
|
17
15
|
DFSOrderPattern,
|
|
16
|
+
EntryCallback,
|
|
18
17
|
IterationType,
|
|
19
18
|
NodeCallback,
|
|
20
19
|
NodePredicate,
|
|
21
|
-
OptNode
|
|
20
|
+
OptNode,
|
|
21
|
+
OptNodeOrNull
|
|
22
22
|
} from '../../types';
|
|
23
23
|
import { BinaryTree, BinaryTreeNode } from './binary-tree';
|
|
24
24
|
import { IBinaryTree } from '../../interfaces';
|
|
@@ -26,61 +26,44 @@ import { Queue } from '../queue';
|
|
|
26
26
|
import { isComparable } from '../../utils';
|
|
27
27
|
import { Range } from '../../common';
|
|
28
28
|
|
|
29
|
-
export class BSTNode<K = any, V = any
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
29
|
+
export class BSTNode<K = any, V = any> extends BinaryTreeNode<K, V> {
|
|
30
|
+
/**
|
|
31
|
+
* This TypeScript constructor function initializes an instance with a key and an optional value.
|
|
32
|
+
* @param {K} key - The `key` parameter is typically used to uniquely identify an object or element
|
|
33
|
+
* within a data structure. It serves as a reference or identifier for accessing or manipulating the
|
|
34
|
+
* associated value.
|
|
35
|
+
* @param {V} [value] - The `value` parameter in the constructor is optional, meaning it does not
|
|
36
|
+
* have to be provided when creating an instance of the class. If a value is not provided, it will
|
|
37
|
+
* default to `undefined`.
|
|
38
|
+
*/
|
|
36
39
|
constructor(key: K, value?: V) {
|
|
37
40
|
super(key, value);
|
|
38
|
-
this.parent = undefined;
|
|
39
|
-
this._left = undefined;
|
|
40
|
-
this._right = undefined;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
override parent?: BSTNode<K, V> = undefined;
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
*/
|
|
49
|
-
override get left(): OptNode<NODE> {
|
|
45
|
+
override _left?: OptNodeOrNull<BSTNode<K, V>> = undefined;
|
|
46
|
+
|
|
47
|
+
override get left(): OptNodeOrNull<BSTNode<K, V>> {
|
|
50
48
|
return this._left;
|
|
51
49
|
}
|
|
52
50
|
|
|
53
|
-
|
|
54
|
-
* The function sets the left child of a node and updates the parent reference of the child.
|
|
55
|
-
* @param {OptNode<NODE>} v - The parameter `v` is of type `OptNode<NODE>`. It can either be an
|
|
56
|
-
* instance of the `NODE` class or `undefined`.
|
|
57
|
-
*/
|
|
58
|
-
override set left(v: OptNode<NODE>) {
|
|
51
|
+
override set left(v: OptNodeOrNull<BSTNode<K, V>>) {
|
|
59
52
|
if (v) {
|
|
60
|
-
v.parent = this
|
|
53
|
+
v.parent = this;
|
|
61
54
|
}
|
|
62
55
|
this._left = v;
|
|
63
56
|
}
|
|
64
57
|
|
|
65
|
-
|
|
58
|
+
override _right?: OptNodeOrNull<BSTNode<K, V>> = undefined;
|
|
66
59
|
|
|
67
|
-
|
|
68
|
-
* The function returns the right node of a binary tree or undefined if there is no right node.
|
|
69
|
-
* @returns The method is returning the value of the `_right` property, which is of type `NODE` or
|
|
70
|
-
* `undefined`.
|
|
71
|
-
*/
|
|
72
|
-
override get right(): OptNode<NODE> {
|
|
60
|
+
override get right(): OptNodeOrNull<BSTNode<K, V>> {
|
|
73
61
|
return this._right;
|
|
74
62
|
}
|
|
75
63
|
|
|
76
|
-
|
|
77
|
-
* The function sets the right child of a node and updates the parent reference of the child.
|
|
78
|
-
* @param {OptNode<NODE>} v - The parameter `v` is of type `OptNode<NODE>`. It can either be a
|
|
79
|
-
* `NODE` object or `undefined`.
|
|
80
|
-
*/
|
|
81
|
-
override set right(v: OptNode<NODE>) {
|
|
64
|
+
override set right(v: OptNodeOrNull<BSTNode<K, V>>) {
|
|
82
65
|
if (v) {
|
|
83
|
-
v.parent = this
|
|
66
|
+
v.parent = this;
|
|
84
67
|
}
|
|
85
68
|
this._right = v;
|
|
86
69
|
}
|
|
@@ -95,32 +78,48 @@ export class BSTNode<K = any, V = any, NODE extends BSTNode<K, V, NODE> = BSTNod
|
|
|
95
78
|
* 6. Balance Variability: Can become unbalanced; special types maintain balance.
|
|
96
79
|
* 7. No Auto-Balancing: Standard BSTs don't automatically balance themselves.
|
|
97
80
|
* @example
|
|
98
|
-
* //
|
|
99
|
-
*
|
|
100
|
-
*
|
|
101
|
-
*
|
|
81
|
+
* // Merge 3 sorted datasets
|
|
82
|
+
* const dataset1 = new BST<number, string>([
|
|
83
|
+
* [1, 'A'],
|
|
84
|
+
* [7, 'G']
|
|
85
|
+
* ]);
|
|
86
|
+
* const dataset2 = [
|
|
87
|
+
* [2, 'B'],
|
|
88
|
+
* [6, 'F']
|
|
89
|
+
* ];
|
|
90
|
+
* const dataset3 = new BST<number, string>([
|
|
91
|
+
* [3, 'C'],
|
|
92
|
+
* [5, 'E'],
|
|
93
|
+
* [4, 'D']
|
|
94
|
+
* ]);
|
|
102
95
|
*
|
|
103
|
-
* //
|
|
104
|
-
* const
|
|
105
|
-
*
|
|
106
|
-
*
|
|
96
|
+
* // Merge datasets into a single BinarySearchTree
|
|
97
|
+
* const merged = new BST<number, string>(dataset1);
|
|
98
|
+
* merged.addMany(dataset2);
|
|
99
|
+
* merged.merge(dataset3);
|
|
107
100
|
*
|
|
108
|
-
* //
|
|
109
|
-
* console.log(
|
|
110
|
-
* console.log(findKthSmallest(3)); // 4
|
|
111
|
-
* console.log(findKthSmallest(7)); // 8
|
|
101
|
+
* // Verify merged dataset is in sorted order
|
|
102
|
+
* console.log([...merged.values()]); // ['A', 'B', 'C', 'D', 'E', 'F', 'G']
|
|
112
103
|
* @example
|
|
113
104
|
* // Find elements in a range
|
|
114
105
|
* const bst = new BST<number>([10, 5, 15, 3, 7, 12, 18]);
|
|
115
106
|
* console.log(bst.search(new Range(5, 10))); // [10, 5, 7]
|
|
116
|
-
* console.log(bst.
|
|
107
|
+
* console.log(bst.rangeSearch([4, 12], node => node.key.toString())); // ['10', '12', '5', '7']
|
|
117
108
|
* console.log(bst.search(new Range(4, 12, true, false))); // [10, 5, 7]
|
|
118
|
-
* console.log(bst.
|
|
109
|
+
* console.log(bst.rangeSearch([15, 20])); // [15, 18]
|
|
119
110
|
* console.log(bst.search(new Range(15, 20, false))); // [18]
|
|
120
111
|
* @example
|
|
121
112
|
* // Find lowest common ancestor
|
|
122
113
|
* const bst = new BST<number>([20, 10, 30, 5, 15, 25, 35, 3, 7, 12, 18]);
|
|
123
114
|
*
|
|
115
|
+
* // LCA helper function
|
|
116
|
+
* const findLCA = (num1: number, num2: number): number | undefined => {
|
|
117
|
+
* const path1 = bst.getPathToRoot(num1);
|
|
118
|
+
* const path2 = bst.getPathToRoot(num2);
|
|
119
|
+
* // Find the first common ancestor
|
|
120
|
+
* return findFirstCommon(path1, path2);
|
|
121
|
+
* };
|
|
122
|
+
*
|
|
124
123
|
* function findFirstCommon(arr1: number[], arr2: number[]): number | undefined {
|
|
125
124
|
* for (const num of arr1) {
|
|
126
125
|
* if (arr2.indexOf(num) !== -1) {
|
|
@@ -130,116 +129,112 @@ export class BSTNode<K = any, V = any, NODE extends BSTNode<K, V, NODE> = BSTNod
|
|
|
130
129
|
* return undefined;
|
|
131
130
|
* }
|
|
132
131
|
*
|
|
133
|
-
* // LCA helper function
|
|
134
|
-
* const findLCA = (num1: number, num2: number): number | undefined => {
|
|
135
|
-
* const path1 = bst.getPathToRoot(num1);
|
|
136
|
-
* const path2 = bst.getPathToRoot(num2);
|
|
137
|
-
* // Find the first common ancestor
|
|
138
|
-
* return findFirstCommon(path1, path2);
|
|
139
|
-
* };
|
|
140
|
-
*
|
|
141
132
|
* // Assertions
|
|
142
133
|
* console.log(findLCA(3, 10)); // 7
|
|
143
134
|
* console.log(findLCA(5, 35)); // 15
|
|
144
135
|
* console.log(findLCA(20, 30)); // 25
|
|
145
136
|
*/
|
|
146
|
-
export class BST<
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
R = object,
|
|
150
|
-
NODE extends BSTNode<K, V, NODE> = BSTNode<K, V, BSTNodeNested<K, V>>,
|
|
151
|
-
TREE extends BST<K, V, R, NODE, TREE> = BST<K, V, R, NODE, BSTNested<K, V, R, NODE>>
|
|
152
|
-
>
|
|
153
|
-
extends BinaryTree<K, V, R, NODE, TREE>
|
|
154
|
-
implements IBinaryTree<K, V, R, NODE, TREE>
|
|
137
|
+
export class BST<K = any, V = any, R = object, MK = any, MV = any, MR = object>
|
|
138
|
+
extends BinaryTree<K, V, R, MK, MV, MR>
|
|
139
|
+
implements IBinaryTree<K, V, R, MK, MV, MR>
|
|
155
140
|
{
|
|
156
141
|
/**
|
|
157
|
-
* This
|
|
158
|
-
*
|
|
159
|
-
*
|
|
160
|
-
*
|
|
161
|
-
*
|
|
162
|
-
*
|
|
142
|
+
* This TypeScript constructor initializes a binary search tree with optional options and adds
|
|
143
|
+
* elements if provided.
|
|
144
|
+
* @param keysNodesEntriesOrRaws - The `keysNodesEntriesOrRaws` parameter in the constructor is an
|
|
145
|
+
* iterable that can contain elements of type `BTNRep<K, V, BSTNode<K, V>>` or `R`. It is used to
|
|
146
|
+
* initialize the binary search tree with keys, nodes, entries, or raw data.
|
|
147
|
+
* @param [options] - The `options` parameter is an optional object that can contain the following
|
|
148
|
+
* properties:
|
|
163
149
|
*/
|
|
164
|
-
constructor(keysNodesEntriesOrRaws: Iterable<
|
|
150
|
+
constructor(keysNodesEntriesOrRaws: Iterable<BTNRep<K, V, BSTNode<K, V>> | R> = [], options?: BSTOptions<K, V, R>) {
|
|
165
151
|
super([], options);
|
|
166
152
|
|
|
167
153
|
if (options) {
|
|
168
|
-
const {
|
|
169
|
-
if (typeof
|
|
154
|
+
const { specifyComparable, isReverse } = options;
|
|
155
|
+
if (typeof specifyComparable === 'function') this._specifyComparable = specifyComparable;
|
|
170
156
|
if (isReverse !== undefined) this._isReverse = isReverse;
|
|
171
157
|
}
|
|
172
158
|
|
|
173
159
|
if (keysNodesEntriesOrRaws) this.addMany(keysNodesEntriesOrRaws);
|
|
174
160
|
}
|
|
175
161
|
|
|
176
|
-
protected override _root?:
|
|
162
|
+
protected override _root?: BSTNode<K, V> = undefined;
|
|
177
163
|
|
|
178
|
-
|
|
179
|
-
* The function returns the root node of a tree structure.
|
|
180
|
-
* @returns The `_root` property of the object, which is of type `NODE` or `undefined`.
|
|
181
|
-
*/
|
|
182
|
-
override get root(): OptNode<NODE> {
|
|
164
|
+
override get root(): OptNode<BSTNode<K, V>> {
|
|
183
165
|
return this._root;
|
|
184
166
|
}
|
|
185
167
|
|
|
186
168
|
protected _isReverse: boolean = false;
|
|
187
169
|
|
|
188
|
-
/**
|
|
189
|
-
* The above function is a getter method in TypeScript that returns the value of the private property
|
|
190
|
-
* `_isReverse`.
|
|
191
|
-
* @returns The `isReverse` property of the object, which is a boolean value.
|
|
192
|
-
*/
|
|
193
170
|
get isReverse(): boolean {
|
|
194
171
|
return this._isReverse;
|
|
195
172
|
}
|
|
196
173
|
|
|
174
|
+
protected _comparator: Comparator<K> = (a: K, b: K): number => {
|
|
175
|
+
if (isComparable(a) && isComparable(b)) {
|
|
176
|
+
if (a > b) return 1;
|
|
177
|
+
if (a < b) return -1;
|
|
178
|
+
return 0;
|
|
179
|
+
}
|
|
180
|
+
if (this._specifyComparable) {
|
|
181
|
+
if (this._specifyComparable(a) > this._specifyComparable(b)) return 1;
|
|
182
|
+
if (this._specifyComparable(a) < this._specifyComparable(b)) return -1;
|
|
183
|
+
return 0;
|
|
184
|
+
}
|
|
185
|
+
if (typeof a === 'object' || typeof b === 'object') {
|
|
186
|
+
throw TypeError(
|
|
187
|
+
`When comparing object types, a custom specifyComparable must be defined in the constructor's options parameter.`
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return 0;
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
get comparator() {
|
|
195
|
+
return this._comparator;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
protected _specifyComparable?: (key: K) => Comparable;
|
|
199
|
+
|
|
200
|
+
get specifyComparable() {
|
|
201
|
+
return this._specifyComparable;
|
|
202
|
+
}
|
|
203
|
+
|
|
197
204
|
/**
|
|
205
|
+
* Time Complexity: O(1)
|
|
206
|
+
* Space Complexity: O(1)
|
|
207
|
+
*
|
|
198
208
|
* The function creates a new BSTNode with the given key and value and returns it.
|
|
199
209
|
* @param {K} key - The key parameter is of type K, which represents the type of the key for the node
|
|
200
210
|
* being created.
|
|
201
211
|
* @param {V} [value] - The "value" parameter is an optional parameter of type V. It represents the
|
|
202
212
|
* value associated with the key in the node being created.
|
|
203
|
-
* @returns The method is returning a new instance of the BSTNode class, casted as the
|
|
213
|
+
* @returns The method is returning a new instance of the BSTNode class, casted as the BSTNode<K, V> type.
|
|
204
214
|
*/
|
|
205
|
-
override createNode(key: K, value?: V):
|
|
206
|
-
return new BSTNode<K, V
|
|
215
|
+
override createNode(key: K, value?: V): BSTNode<K, V> {
|
|
216
|
+
return new BSTNode<K, V>(key, this._isMapMode ? undefined : value);
|
|
207
217
|
}
|
|
208
218
|
|
|
209
219
|
/**
|
|
220
|
+
* Time Complexity: O(1)
|
|
221
|
+
* Space Complexity: O(1)
|
|
222
|
+
*
|
|
210
223
|
* The function creates a new binary search tree with the specified options.
|
|
211
224
|
* @param [options] - The `options` parameter is an optional object that allows you to customize the
|
|
212
225
|
* behavior of the `createTree` method. It accepts a partial `BSTOptions` object, which has the
|
|
213
226
|
* following properties:
|
|
214
227
|
* @returns a new instance of the BST class with the provided options.
|
|
215
228
|
*/
|
|
216
|
-
override createTree(options?: BSTOptions<K, V, R>)
|
|
217
|
-
return new BST<K, V, R,
|
|
229
|
+
override createTree(options?: BSTOptions<K, V, R>) {
|
|
230
|
+
return new BST<K, V, R, MK, MV, MR>([], {
|
|
218
231
|
iterationType: this.iterationType,
|
|
219
232
|
isMapMode: this._isMapMode,
|
|
220
|
-
|
|
233
|
+
specifyComparable: this._specifyComparable,
|
|
221
234
|
toEntryFn: this._toEntryFn,
|
|
222
235
|
isReverse: this._isReverse,
|
|
223
236
|
...options
|
|
224
|
-
})
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
/**
|
|
228
|
-
* The function overrides a method and converts a key, value pair or entry or raw element to a node.
|
|
229
|
-
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - A variable that can be of
|
|
230
|
-
* type R or BTNRep<K, V, NODE>. It represents either a key, a node, an entry, or a raw
|
|
231
|
-
* element.
|
|
232
|
-
* @param {V} [value] - The `value` parameter is an optional value of type `V`. It represents the
|
|
233
|
-
* value associated with a key in a key-value pair.
|
|
234
|
-
* @returns either a NODE object or undefined.
|
|
235
|
-
*/
|
|
236
|
-
override keyValueNodeEntryRawToNodeAndValue(
|
|
237
|
-
keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R,
|
|
238
|
-
value?: V
|
|
239
|
-
): [OptNode<NODE>, V | undefined] {
|
|
240
|
-
const [node, entryValue] = super.keyValueNodeEntryRawToNodeAndValue(keyNodeEntryOrRaw, value);
|
|
241
|
-
if (node === null) return [undefined, undefined];
|
|
242
|
-
return [node, value ?? entryValue];
|
|
237
|
+
});
|
|
243
238
|
}
|
|
244
239
|
|
|
245
240
|
/**
|
|
@@ -248,8 +243,8 @@ export class BST<
|
|
|
248
243
|
*
|
|
249
244
|
* The function ensures the existence of a node in a data structure and returns it, or undefined if
|
|
250
245
|
* it doesn't exist.
|
|
251
|
-
* @param {BTNRep<K, V,
|
|
252
|
-
* `
|
|
246
|
+
* @param {BTNRep<K, V, BSTNode<K, V>>} keyNodeOrEntry - The parameter
|
|
247
|
+
* `keyNodeOrEntry` can accept a value of type `R`, which represents the key, node,
|
|
253
248
|
* entry, or raw element that needs to be ensured in the tree.
|
|
254
249
|
* @param {IterationType} [iterationType=ITERATIVE] - The `iterationType` parameter is an optional
|
|
255
250
|
* parameter that specifies the type of iteration to be used when ensuring a node. It has a default
|
|
@@ -258,48 +253,54 @@ export class BST<
|
|
|
258
253
|
* not be ensured.
|
|
259
254
|
*/
|
|
260
255
|
override ensureNode(
|
|
261
|
-
|
|
256
|
+
keyNodeOrEntry: BTNRep<K, V, BSTNode<K, V>>,
|
|
262
257
|
iterationType: IterationType = this.iterationType
|
|
263
|
-
): OptNode<
|
|
264
|
-
return super.ensureNode(
|
|
258
|
+
): OptNode<BSTNode<K, V>> {
|
|
259
|
+
return super.ensureNode(keyNodeOrEntry, iterationType) ?? undefined;
|
|
265
260
|
}
|
|
266
261
|
|
|
267
262
|
/**
|
|
263
|
+
* Time Complexity: O(1)
|
|
264
|
+
* Space Complexity: O(1)
|
|
265
|
+
*
|
|
268
266
|
* The function checks if the input is an instance of the BSTNode class.
|
|
269
|
-
* @param {BTNRep<K, V,
|
|
270
|
-
* `
|
|
271
|
-
* @returns a boolean value indicating whether the input parameter `
|
|
267
|
+
* @param {BTNRep<K, V, BSTNode<K, V>>} keyNodeOrEntry - The parameter
|
|
268
|
+
* `keyNodeOrEntry` can be of type `R` or `BTNRep<K, V, BSTNode<K, V>>`.
|
|
269
|
+
* @returns a boolean value indicating whether the input parameter `keyNodeOrEntry` is
|
|
272
270
|
* an instance of the `BSTNode` class.
|
|
273
271
|
*/
|
|
274
|
-
override isNode(
|
|
275
|
-
return
|
|
272
|
+
override isNode(keyNodeOrEntry: BTNRep<K, V, BSTNode<K, V>>): keyNodeOrEntry is BSTNode<K, V> {
|
|
273
|
+
return keyNodeOrEntry instanceof BSTNode;
|
|
276
274
|
}
|
|
277
275
|
|
|
278
276
|
/**
|
|
279
|
-
*
|
|
277
|
+
* Time Complexity: O(1)
|
|
278
|
+
* Space Complexity: O(1)
|
|
279
|
+
*
|
|
280
|
+
* The function "override isValidKey" checks if a key is comparable based on a given comparator.
|
|
280
281
|
* @param {any} key - The `key` parameter is a value that will be checked to determine if it is of
|
|
281
282
|
* type `K`.
|
|
282
|
-
* @returns The `override
|
|
283
|
+
* @returns The `override isValidKey(key: any): key is K` function is returning a boolean value based on
|
|
283
284
|
* the result of the `isComparable` function with the condition `this._compare !==
|
|
284
285
|
* this._DEFAULT_COMPARATOR`.
|
|
285
286
|
*/
|
|
286
|
-
override
|
|
287
|
-
return isComparable(key, this.
|
|
287
|
+
override isValidKey(key: any): key is K {
|
|
288
|
+
return isComparable(key, this._specifyComparable !== undefined);
|
|
288
289
|
}
|
|
289
290
|
|
|
290
291
|
/**
|
|
291
292
|
* Time Complexity: O(log n)
|
|
292
|
-
* Space Complexity: O(
|
|
293
|
+
* Space Complexity: O(log n)
|
|
293
294
|
*
|
|
294
295
|
* The `add` function in TypeScript adds a new node to a binary search tree based on the key value.
|
|
295
|
-
* @param {BTNRep<K, V,
|
|
296
|
-
* `
|
|
296
|
+
* @param {BTNRep<K, V, BSTNode<K, V>>} keyNodeOrEntry - The parameter
|
|
297
|
+
* `keyNodeOrEntry` can accept a value of type `R` or `BTNRep<K, V, BSTNode<K, V>>`.
|
|
297
298
|
* @param {V} [value] - The `value` parameter is an optional value that can be associated with the
|
|
298
299
|
* key in the binary search tree. If provided, it will be stored in the node along with the key.
|
|
299
300
|
* @returns a boolean value.
|
|
300
301
|
*/
|
|
301
|
-
override add(
|
|
302
|
-
const [newNode, newValue] = this.
|
|
302
|
+
override add(keyNodeOrEntry: BTNRep<K, V, BSTNode<K, V>>, value?: V): boolean {
|
|
303
|
+
const [newNode, newValue] = this._keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value);
|
|
303
304
|
if (newNode === undefined) return false;
|
|
304
305
|
|
|
305
306
|
if (this._root === undefined) {
|
|
@@ -322,7 +323,7 @@ export class BST<
|
|
|
322
323
|
this._size++;
|
|
323
324
|
return true;
|
|
324
325
|
}
|
|
325
|
-
current = current.left;
|
|
326
|
+
if (current.left !== null) current = current.left;
|
|
326
327
|
} else {
|
|
327
328
|
if (current.right === undefined) {
|
|
328
329
|
current.right = newNode;
|
|
@@ -330,7 +331,7 @@ export class BST<
|
|
|
330
331
|
this._size++;
|
|
331
332
|
return true;
|
|
332
333
|
}
|
|
333
|
-
current = current.right;
|
|
334
|
+
if (current.right !== null) current = current.right;
|
|
334
335
|
}
|
|
335
336
|
}
|
|
336
337
|
|
|
@@ -359,7 +360,7 @@ export class BST<
|
|
|
359
360
|
* successfully inserted into the data structure.
|
|
360
361
|
*/
|
|
361
362
|
override addMany(
|
|
362
|
-
keysNodesEntriesOrRaws: Iterable<R | BTNRep<K, V,
|
|
363
|
+
keysNodesEntriesOrRaws: Iterable<R | BTNRep<K, V, BSTNode<K, V>>>,
|
|
363
364
|
values?: Iterable<V | undefined>,
|
|
364
365
|
isBalanceAdd = true,
|
|
365
366
|
iterationType: IterationType = this.iterationType
|
|
@@ -373,15 +374,16 @@ export class BST<
|
|
|
373
374
|
}
|
|
374
375
|
|
|
375
376
|
if (!isBalanceAdd) {
|
|
376
|
-
for (
|
|
377
|
+
for (let kve of keysNodesEntriesOrRaws) {
|
|
377
378
|
const value = valuesIterator?.next().value;
|
|
379
|
+
if (this.isRaw(kve)) kve = this._toEntryFn!(kve);
|
|
378
380
|
inserted.push(this.add(kve, value));
|
|
379
381
|
}
|
|
380
382
|
return inserted;
|
|
381
383
|
}
|
|
382
384
|
|
|
383
385
|
const realBTNExemplars: {
|
|
384
|
-
key: R | BTNRep<K, V,
|
|
386
|
+
key: R | BTNRep<K, V, BSTNode<K, V>>;
|
|
385
387
|
value: V | undefined;
|
|
386
388
|
orgIndex: number;
|
|
387
389
|
}[] = [];
|
|
@@ -392,23 +394,21 @@ export class BST<
|
|
|
392
394
|
i++;
|
|
393
395
|
}
|
|
394
396
|
|
|
395
|
-
let sorted: { key: R | BTNRep<K, V,
|
|
397
|
+
let sorted: { key: R | BTNRep<K, V, BSTNode<K, V>>; value: V | undefined; orgIndex: number }[] = [];
|
|
396
398
|
|
|
397
399
|
sorted = realBTNExemplars.sort(({ key: a }, { key: b }) => {
|
|
398
400
|
let keyA: K | undefined | null, keyB: K | undefined | null;
|
|
399
|
-
if (this.
|
|
401
|
+
if (this.isRaw(a)) keyA = this._toEntryFn!(a)[0];
|
|
402
|
+
else if (this.isEntry(a)) keyA = a[0];
|
|
400
403
|
else if (this.isRealNode(a)) keyA = a.key;
|
|
401
|
-
else
|
|
402
|
-
keyA = this._toEntryFn(a as R)[0];
|
|
403
|
-
} else {
|
|
404
|
+
else {
|
|
404
405
|
keyA = a as K;
|
|
405
406
|
}
|
|
406
407
|
|
|
407
|
-
if (this.
|
|
408
|
+
if (this.isRaw(b)) keyB = this._toEntryFn!(b)[0];
|
|
409
|
+
else if (this.isEntry(b)) keyB = b[0];
|
|
408
410
|
else if (this.isRealNode(b)) keyB = b.key;
|
|
409
|
-
else
|
|
410
|
-
keyB = this._toEntryFn(b as R)[0];
|
|
411
|
-
} else {
|
|
411
|
+
else {
|
|
412
412
|
keyB = b as K;
|
|
413
413
|
}
|
|
414
414
|
|
|
@@ -418,11 +418,17 @@ export class BST<
|
|
|
418
418
|
return 0;
|
|
419
419
|
});
|
|
420
420
|
|
|
421
|
-
const _dfs = (arr: { key: R | BTNRep<K, V,
|
|
421
|
+
const _dfs = (arr: { key: R | BTNRep<K, V, BSTNode<K, V>>; value: V | undefined; orgIndex: number }[]) => {
|
|
422
422
|
if (arr.length === 0) return;
|
|
423
423
|
|
|
424
424
|
const mid = Math.floor((arr.length - 1) / 2);
|
|
425
|
-
|
|
425
|
+
let { key, value } = arr[mid];
|
|
426
|
+
const { orgIndex } = arr[mid];
|
|
427
|
+
if (this.isRaw(key)) {
|
|
428
|
+
const entry = this._toEntryFn!(key);
|
|
429
|
+
key = entry[0];
|
|
430
|
+
value = entry[1] ?? value;
|
|
431
|
+
}
|
|
426
432
|
inserted[orgIndex] = this.add(key, value);
|
|
427
433
|
_dfs(arr.slice(0, mid));
|
|
428
434
|
_dfs(arr.slice(mid + 1));
|
|
@@ -437,7 +443,13 @@ export class BST<
|
|
|
437
443
|
const [l, r] = popped;
|
|
438
444
|
if (l <= r) {
|
|
439
445
|
const m = l + Math.floor((r - l) / 2);
|
|
440
|
-
|
|
446
|
+
let { key, value } = sorted[m];
|
|
447
|
+
const { orgIndex } = sorted[m];
|
|
448
|
+
if (this.isRaw(key)) {
|
|
449
|
+
const entry = this._toEntryFn!(key);
|
|
450
|
+
key = entry[0];
|
|
451
|
+
value = entry[1] ?? value;
|
|
452
|
+
}
|
|
441
453
|
inserted[orgIndex] = this.add(key, value);
|
|
442
454
|
stack.push([m + 1, r]);
|
|
443
455
|
stack.push([l, m - 1]);
|
|
@@ -455,36 +467,23 @@ export class BST<
|
|
|
455
467
|
return inserted;
|
|
456
468
|
}
|
|
457
469
|
|
|
458
|
-
/**
|
|
459
|
-
* Time Complexity: O(n)
|
|
460
|
-
* Space Complexity: O(1)
|
|
461
|
-
*
|
|
462
|
-
* The `merge` function overrides the base class method by adding elements from another
|
|
463
|
-
* binary search tree.
|
|
464
|
-
* @param anotherTree - `anotherTree` is an instance of a Binary Search Tree (BST) with key type `K`,
|
|
465
|
-
* value type `V`, return type `R`, node type `NODE`, and tree type `TREE`.
|
|
466
|
-
*/
|
|
467
|
-
override merge(anotherTree: BST<K, V, R, NODE, TREE>) {
|
|
468
|
-
this.addMany(anotherTree, [], false);
|
|
469
|
-
}
|
|
470
|
-
|
|
471
470
|
/**
|
|
472
471
|
* Time Complexity: O(log n)
|
|
473
472
|
* Space Complexity: O(k + log n)
|
|
474
473
|
*
|
|
475
474
|
* The function `search` in TypeScript overrides the search behavior in a binary tree structure based
|
|
476
475
|
* on specified criteria.
|
|
477
|
-
* @param {BTNRep<K, V,
|
|
478
|
-
* `
|
|
476
|
+
* @param {BTNRep<K, V, BSTNode<K, V>> | NodePredicate<BSTNode<K, V>>} keyNodeEntryOrPredicate - The
|
|
477
|
+
* `keyNodeEntryOrPredicate` parameter in the `override search` method can accept one of the
|
|
479
478
|
* following types:
|
|
480
479
|
* @param [onlyOne=false] - The `onlyOne` parameter is a boolean flag that determines whether the
|
|
481
480
|
* search should stop after finding the first matching node. If `onlyOne` is set to `true`, the
|
|
482
481
|
* search will return as soon as a matching node is found. If `onlyOne` is set to `false`, the
|
|
483
482
|
* @param {C} callback - The `callback` parameter in the `override search` function is a function
|
|
484
483
|
* that will be called on each node that matches the search criteria. It is of type `C`, which
|
|
485
|
-
* extends `NodeCallback<
|
|
484
|
+
* extends `NodeCallback<BSTNode<K, V>>`. The callback function should accept a node of type `BSTNode<K, V>` as its
|
|
486
485
|
* argument and
|
|
487
|
-
* @param {BTNRep<K, V,
|
|
486
|
+
* @param {BTNRep<K, V, BSTNode<K, V>>} startNode - The `startNode` parameter in the `override search`
|
|
488
487
|
* method represents the node from which the search operation will begin. It is the starting point
|
|
489
488
|
* for searching within the tree data structure. The method ensures that the `startNode` is a valid
|
|
490
489
|
* node before proceeding with the search operation. If the `
|
|
@@ -496,29 +495,29 @@ export class BST<
|
|
|
496
495
|
* structure based on the provided key, predicate, and other options. The search results are
|
|
497
496
|
* collected in an array and returned as the output of the method.
|
|
498
497
|
*/
|
|
499
|
-
override search<C extends NodeCallback<
|
|
500
|
-
|
|
498
|
+
override search<C extends NodeCallback<BSTNode<K, V>>>(
|
|
499
|
+
keyNodeEntryOrPredicate: BTNRep<K, V, BSTNode<K, V>> | NodePredicate<BSTNode<K, V>> | Range<K>,
|
|
501
500
|
onlyOne = false,
|
|
502
501
|
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
503
|
-
startNode: BTNRep<K, V,
|
|
502
|
+
startNode: BTNRep<K, V, BSTNode<K, V>> = this._root,
|
|
504
503
|
iterationType: IterationType = this.iterationType
|
|
505
504
|
): ReturnType<C>[] {
|
|
506
|
-
if (
|
|
507
|
-
if (
|
|
505
|
+
if (keyNodeEntryOrPredicate === undefined) return [];
|
|
506
|
+
if (keyNodeEntryOrPredicate === null) return [];
|
|
508
507
|
startNode = this.ensureNode(startNode);
|
|
509
508
|
if (!startNode) return [];
|
|
510
|
-
let predicate: NodePredicate<
|
|
509
|
+
let predicate: NodePredicate<BSTNode<K, V>>;
|
|
511
510
|
|
|
512
|
-
const isRange = this.isRange(
|
|
511
|
+
const isRange = this.isRange(keyNodeEntryOrPredicate);
|
|
513
512
|
// Set predicate based on parameter type
|
|
514
513
|
if (isRange) {
|
|
515
|
-
predicate = node =>
|
|
514
|
+
predicate = node => keyNodeEntryOrPredicate.isInRange(node.key, this._comparator);
|
|
516
515
|
} else {
|
|
517
|
-
predicate = this._ensurePredicate(
|
|
516
|
+
predicate = this._ensurePredicate(keyNodeEntryOrPredicate);
|
|
518
517
|
}
|
|
519
|
-
const isToLeftByRange = (cur:
|
|
518
|
+
const isToLeftByRange = (cur: BSTNode<K, V>) => {
|
|
520
519
|
if (isRange) {
|
|
521
|
-
const range =
|
|
520
|
+
const range = keyNodeEntryOrPredicate;
|
|
522
521
|
const leftS = this.isReverse ? range.high : range.low;
|
|
523
522
|
const leftI = this.isReverse ? range.includeHigh : range.includeLow;
|
|
524
523
|
return (leftI && this._compare(cur.key, leftS) >= 0) || (!leftI && this._compare(cur.key, leftS) > 0);
|
|
@@ -526,9 +525,9 @@ export class BST<
|
|
|
526
525
|
return false;
|
|
527
526
|
};
|
|
528
527
|
|
|
529
|
-
const isToRightByRange = (cur:
|
|
528
|
+
const isToRightByRange = (cur: BSTNode<K, V>) => {
|
|
530
529
|
if (isRange) {
|
|
531
|
-
const range =
|
|
530
|
+
const range = keyNodeEntryOrPredicate;
|
|
532
531
|
const rightS = this.isReverse ? range.low : range.high;
|
|
533
532
|
const rightI = this.isReverse ? range.includeLow : range.includeLow;
|
|
534
533
|
|
|
@@ -538,7 +537,7 @@ export class BST<
|
|
|
538
537
|
};
|
|
539
538
|
const ans: ReturnType<C>[] = [];
|
|
540
539
|
if (iterationType === 'RECURSIVE') {
|
|
541
|
-
const dfs = (cur:
|
|
540
|
+
const dfs = (cur: BSTNode<K, V>) => {
|
|
542
541
|
if (predicate(cur)) {
|
|
543
542
|
ans.push(callback(cur));
|
|
544
543
|
if (onlyOne) return;
|
|
@@ -549,8 +548,8 @@ export class BST<
|
|
|
549
548
|
if (isRange) {
|
|
550
549
|
if (this.isRealNode(cur.left) && isToLeftByRange(cur)) dfs(cur.left);
|
|
551
550
|
if (this.isRealNode(cur.right) && isToRightByRange(cur)) dfs(cur.right);
|
|
552
|
-
} else if (!this._isPredicate(
|
|
553
|
-
const benchmarkKey = this._extractKey(
|
|
551
|
+
} else if (!this._isPredicate(keyNodeEntryOrPredicate)) {
|
|
552
|
+
const benchmarkKey = this._extractKey(keyNodeEntryOrPredicate);
|
|
554
553
|
if (
|
|
555
554
|
this.isRealNode(cur.left) &&
|
|
556
555
|
benchmarkKey !== null &&
|
|
@@ -583,8 +582,8 @@ export class BST<
|
|
|
583
582
|
if (isRange) {
|
|
584
583
|
if (this.isRealNode(cur.left) && isToLeftByRange(cur)) stack.push(cur.left);
|
|
585
584
|
if (this.isRealNode(cur.right) && isToRightByRange(cur)) stack.push(cur.right);
|
|
586
|
-
} else if (!this._isPredicate(
|
|
587
|
-
const benchmarkKey = this._extractKey(
|
|
585
|
+
} else if (!this._isPredicate(keyNodeEntryOrPredicate)) {
|
|
586
|
+
const benchmarkKey = this._extractKey(keyNodeEntryOrPredicate);
|
|
588
587
|
if (
|
|
589
588
|
this.isRealNode(cur.right) &&
|
|
590
589
|
benchmarkKey !== null &&
|
|
@@ -611,12 +610,43 @@ export class BST<
|
|
|
611
610
|
|
|
612
611
|
/**
|
|
613
612
|
* Time Complexity: O(log n)
|
|
614
|
-
* Space Complexity: O(
|
|
613
|
+
* Space Complexity: O(k + log n)
|
|
614
|
+
*
|
|
615
|
+
* The `rangeSearch` function searches for nodes within a specified range in a binary search tree.
|
|
616
|
+
* @param {Range<K> | [K, K]} range - The `range` parameter in the `rangeSearch` function can be
|
|
617
|
+
* either a `Range` object or an array of two elements representing the range boundaries.
|
|
618
|
+
* @param {C} callback - The `callback` parameter in the `rangeSearch` function is a callback
|
|
619
|
+
* function that is used to process each node that is found within the specified range during the
|
|
620
|
+
* search operation. It is of type `NodeCallback<BSTNode<K, V>>`, where `BSTNode<K, V>` is the type of nodes in the
|
|
621
|
+
* data structure.
|
|
622
|
+
* @param {BTNRep<K, V, BSTNode<K, V>>} startNode - The `startNode` parameter in the `rangeSearch`
|
|
623
|
+
* function represents the node from which the search for nodes within the specified range will
|
|
624
|
+
* begin. It is the starting point for the range search operation.
|
|
625
|
+
* @param {IterationType} iterationType - The `iterationType` parameter in the `rangeSearch` function
|
|
626
|
+
* is used to specify the type of iteration to be performed during the search operation. It has a
|
|
627
|
+
* default value of `this.iterationType`, which suggests that it is likely a property of the class or
|
|
628
|
+
* object that the `rangeSearch`
|
|
629
|
+
* @returns The `rangeSearch` function is returning the result of calling the `search` method with
|
|
630
|
+
* the specified parameters.
|
|
631
|
+
*/
|
|
632
|
+
rangeSearch<C extends NodeCallback<BSTNode<K, V>>>(
|
|
633
|
+
range: Range<K> | [K, K],
|
|
634
|
+
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
635
|
+
startNode: BTNRep<K, V, BSTNode<K, V>> = this._root,
|
|
636
|
+
iterationType: IterationType = this.iterationType
|
|
637
|
+
) {
|
|
638
|
+
const searchRange: Range<K> = range instanceof Range ? range : new Range(range[0], range[1]);
|
|
639
|
+
return this.search(searchRange, false, callback, startNode, iterationType);
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
/**
|
|
643
|
+
* Time Complexity: O(log n)
|
|
644
|
+
* Space Complexity: O(log n)
|
|
615
645
|
*
|
|
616
|
-
* This function retrieves a node based on a given
|
|
617
|
-
* @param {BTNRep<K, V,
|
|
618
|
-
* parameter can be of type `BTNRep<K, V,
|
|
619
|
-
* @param {
|
|
646
|
+
* This function retrieves a node based on a given keyNodeEntryOrPredicate within a binary search tree structure.
|
|
647
|
+
* @param {BTNRep<K, V, BSTNode<K, V>> | NodePredicate<BSTNode<K, V>>} keyNodeEntryOrPredicate - The `keyNodeEntryOrPredicate`
|
|
648
|
+
* parameter can be of type `BTNRep<K, V, BSTNode<K, V>>`, `R`, or `NodePredicate<BSTNode<K, V>>`.
|
|
649
|
+
* @param {BSTNOptKeyOrNode<K, BSTNode<K, V>>} startNode - The `startNode` parameter in the `getNode` method
|
|
620
650
|
* is used to specify the starting point for searching nodes in the binary search tree. If no
|
|
621
651
|
* specific starting point is provided, the default value is set to `this._root`, which is the root
|
|
622
652
|
* node of the binary search tree.
|
|
@@ -624,17 +654,17 @@ export class BST<
|
|
|
624
654
|
* parameter that specifies the type of iteration to be used. It has a default value of
|
|
625
655
|
* `this.iterationType`, which means it will use the iteration type defined in the class instance if
|
|
626
656
|
* no value is provided when calling the method.
|
|
627
|
-
* @returns The `getNode` method is returning an optional binary search tree node (`OptNode<
|
|
628
|
-
* It is using the `getNodes` method to find the node based on the provided
|
|
657
|
+
* @returns The `getNode` method is returning an optional binary search tree node (`OptNode<BSTNode<K, V>>`).
|
|
658
|
+
* It is using the `getNodes` method to find the node based on the provided keyNodeEntryOrPredicate, beginning at
|
|
629
659
|
* the specified root node (`startNode`) and using the specified iteration type. The method then
|
|
630
660
|
* returns the first node found or `undefined` if no node is found.
|
|
631
661
|
*/
|
|
632
662
|
override getNode(
|
|
633
|
-
|
|
634
|
-
startNode:
|
|
663
|
+
keyNodeEntryOrPredicate: BTNRep<K, V, BSTNode<K, V>> | NodePredicate<BSTNode<K, V>>,
|
|
664
|
+
startNode: BSTNOptKeyOrNode<K, BSTNode<K, V>> = this._root,
|
|
635
665
|
iterationType: IterationType = this.iterationType
|
|
636
|
-
): OptNode<
|
|
637
|
-
return this.getNodes(
|
|
666
|
+
): OptNode<BSTNode<K, V>> {
|
|
667
|
+
return this.getNodes(keyNodeEntryOrPredicate, true, startNode, iterationType)[0] ?? undefined;
|
|
638
668
|
}
|
|
639
669
|
|
|
640
670
|
/**
|
|
@@ -649,7 +679,7 @@ export class BST<
|
|
|
649
679
|
* @param {DFSOrderPattern} [pattern=IN] - The "pattern" parameter in the code snippet refers to the
|
|
650
680
|
* order in which the Depth-First Search (DFS) algorithm visits the nodes in a tree or graph. It can
|
|
651
681
|
* take one of the following values:
|
|
652
|
-
* @param {BTNRep<K, V,
|
|
682
|
+
* @param {BTNRep<K, V, BSTNode<K, V>>} startNode - The `startNode` parameter is the starting
|
|
653
683
|
* point for the depth-first search traversal. It can be either a root node, a key-value pair, or a
|
|
654
684
|
* node entry. If not specified, the default value is the root of the tree.
|
|
655
685
|
* @param {IterationType} [iterationType=ITERATIVE] - The `iterationType` parameter specifies the
|
|
@@ -657,10 +687,10 @@ export class BST<
|
|
|
657
687
|
* following values:
|
|
658
688
|
* @returns The method is returning an array of the return type of the callback function.
|
|
659
689
|
*/
|
|
660
|
-
override dfs<C extends NodeCallback<
|
|
690
|
+
override dfs<C extends NodeCallback<BSTNode<K, V>>>(
|
|
661
691
|
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
662
692
|
pattern: DFSOrderPattern = 'IN',
|
|
663
|
-
startNode: BTNRep<K, V,
|
|
693
|
+
startNode: BTNRep<K, V, BSTNode<K, V>> = this._root,
|
|
664
694
|
iterationType: IterationType = this.iterationType
|
|
665
695
|
): ReturnType<C>[] {
|
|
666
696
|
return super.dfs(callback, pattern, startNode, iterationType);
|
|
@@ -675,7 +705,7 @@ export class BST<
|
|
|
675
705
|
* @param {C} callback - The `callback` parameter is a function that will be called for each node
|
|
676
706
|
* visited during the breadth-first search. It should take a single argument, which is the current
|
|
677
707
|
* node being visited, and it can return a value of any type.
|
|
678
|
-
* @param {BTNRep<K, V,
|
|
708
|
+
* @param {BTNRep<K, V, BSTNode<K, V>>} startNode - The `startNode` parameter is the starting
|
|
679
709
|
* point for the breadth-first search. It can be either a root node, a key-value pair, or an entry
|
|
680
710
|
* object. If no value is provided, the default value is the root of the tree.
|
|
681
711
|
* @param {IterationType} iterationType - The `iterationType` parameter is used to specify the type
|
|
@@ -683,9 +713,9 @@ export class BST<
|
|
|
683
713
|
* the following values:
|
|
684
714
|
* @returns an array of the return type of the callback function.
|
|
685
715
|
*/
|
|
686
|
-
override bfs<C extends NodeCallback<
|
|
716
|
+
override bfs<C extends NodeCallback<BSTNode<K, V>>>(
|
|
687
717
|
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
688
|
-
startNode: BTNRep<K, V,
|
|
718
|
+
startNode: BTNRep<K, V, BSTNode<K, V>> = this._root,
|
|
689
719
|
iterationType: IterationType = this.iterationType
|
|
690
720
|
): ReturnType<C>[] {
|
|
691
721
|
return super.bfs(callback, startNode, iterationType, false);
|
|
@@ -698,9 +728,9 @@ export class BST<
|
|
|
698
728
|
* The function overrides the listLevels method from the superclass and returns an array of arrays
|
|
699
729
|
* containing the results of the callback function applied to each level of the tree.
|
|
700
730
|
* @param {C} callback - The `callback` parameter is a generic type `C` that extends
|
|
701
|
-
* `NodeCallback<
|
|
731
|
+
* `NodeCallback<BSTNode<K, V>>`. It represents a callback function that will be called for each node in the
|
|
702
732
|
* tree during the iteration process.
|
|
703
|
-
* @param {BTNRep<K, V,
|
|
733
|
+
* @param {BTNRep<K, V, BSTNode<K, V>>} startNode - The `startNode` parameter is the starting
|
|
704
734
|
* point for listing the levels of the binary tree. It can be either a root node of the tree, a
|
|
705
735
|
* key-value pair representing a node in the tree, or a key representing a node in the tree. If no
|
|
706
736
|
* value is provided, the root of
|
|
@@ -709,9 +739,9 @@ export class BST<
|
|
|
709
739
|
* @returns The method is returning a two-dimensional array of the return type of the callback
|
|
710
740
|
* function.
|
|
711
741
|
*/
|
|
712
|
-
override listLevels<C extends NodeCallback<
|
|
742
|
+
override listLevels<C extends NodeCallback<BSTNode<K, V>>>(
|
|
713
743
|
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
714
|
-
startNode: BTNRep<K, V,
|
|
744
|
+
startNode: BTNRep<K, V, BSTNode<K, V>> = this._root,
|
|
715
745
|
iterationType: IterationType = this.iterationType
|
|
716
746
|
): ReturnType<C>[][] {
|
|
717
747
|
return super.listLevels(callback, startNode, iterationType, false);
|
|
@@ -729,7 +759,7 @@ export class BST<
|
|
|
729
759
|
* @param {CP} lesserOrGreater - The `lesserOrGreater` parameter is used to determine whether to
|
|
730
760
|
* traverse nodes that are lesser, greater, or both than the `targetNode`. It accepts the values -1,
|
|
731
761
|
* 0, or 1, where:
|
|
732
|
-
* @param {BTNRep<K, V,
|
|
762
|
+
* @param {BTNRep<K, V, BSTNode<K, V>>} targetNode - The `targetNode` parameter is the node in
|
|
733
763
|
* the binary tree that you want to start traversing from. It can be specified either by providing
|
|
734
764
|
* the key of the node, the node itself, or an entry containing the key and value of the node. If no
|
|
735
765
|
* `targetNode` is provided,
|
|
@@ -738,21 +768,21 @@ export class BST<
|
|
|
738
768
|
* @returns The function `lesserOrGreaterTraverse` returns an array of values of type
|
|
739
769
|
* `ReturnType<C>`, which is the return type of the callback function passed as an argument.
|
|
740
770
|
*/
|
|
741
|
-
lesserOrGreaterTraverse<C extends NodeCallback<
|
|
771
|
+
lesserOrGreaterTraverse<C extends NodeCallback<BSTNode<K, V>>>(
|
|
742
772
|
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
743
773
|
lesserOrGreater: CP = -1,
|
|
744
|
-
targetNode: BTNRep<K, V,
|
|
774
|
+
targetNode: BTNRep<K, V, BSTNode<K, V>> = this._root,
|
|
745
775
|
iterationType: IterationType = this.iterationType
|
|
746
776
|
): ReturnType<C>[] {
|
|
747
777
|
const targetNodeEnsured = this.ensureNode(targetNode);
|
|
748
|
-
const ans: ReturnType<NodeCallback<
|
|
778
|
+
const ans: ReturnType<NodeCallback<BSTNode<K, V>>>[] = [];
|
|
749
779
|
if (!this._root) return ans;
|
|
750
780
|
if (!targetNodeEnsured) return ans;
|
|
751
781
|
|
|
752
782
|
const targetKey = targetNodeEnsured.key;
|
|
753
783
|
|
|
754
784
|
if (iterationType === 'RECURSIVE') {
|
|
755
|
-
const dfs = (cur:
|
|
785
|
+
const dfs = (cur: BSTNode<K, V>) => {
|
|
756
786
|
const compared = this._compare(cur.key, targetKey);
|
|
757
787
|
if (Math.sign(compared) === lesserOrGreater) ans.push(callback(cur));
|
|
758
788
|
// TODO here can be optimized to O(log n)
|
|
@@ -763,7 +793,7 @@ export class BST<
|
|
|
763
793
|
dfs(this._root);
|
|
764
794
|
return ans;
|
|
765
795
|
} else {
|
|
766
|
-
const queue = new Queue<
|
|
796
|
+
const queue = new Queue<BSTNode<K, V>>([this._root]);
|
|
767
797
|
while (queue.size > 0) {
|
|
768
798
|
const cur = queue.shift();
|
|
769
799
|
if (this.isRealNode(cur)) {
|
|
@@ -847,7 +877,7 @@ export class BST<
|
|
|
847
877
|
let balanced = true;
|
|
848
878
|
|
|
849
879
|
if (iterationType === 'RECURSIVE') {
|
|
850
|
-
const _height = (cur:
|
|
880
|
+
const _height = (cur: OptNodeOrNull<BSTNode<K, V>>): number => {
|
|
851
881
|
if (!cur) return 0;
|
|
852
882
|
const leftHeight = _height(cur.left),
|
|
853
883
|
rightHeight = _height(cur.right);
|
|
@@ -856,15 +886,15 @@ export class BST<
|
|
|
856
886
|
};
|
|
857
887
|
_height(this._root);
|
|
858
888
|
} else {
|
|
859
|
-
const stack:
|
|
860
|
-
let node: OptNode<
|
|
861
|
-
last: OptNode<
|
|
862
|
-
const depths: Map<
|
|
889
|
+
const stack: BSTNode<K, V>[] = [];
|
|
890
|
+
let node: OptNode<BSTNode<K, V>> = this._root,
|
|
891
|
+
last: OptNode<BSTNode<K, V>> = undefined;
|
|
892
|
+
const depths: Map<BSTNode<K, V>, number> = new Map();
|
|
863
893
|
|
|
864
894
|
while (stack.length > 0 || node) {
|
|
865
895
|
if (node) {
|
|
866
896
|
stack.push(node);
|
|
867
|
-
node = node.left;
|
|
897
|
+
if (node.left !== null) node = node.left;
|
|
868
898
|
} else {
|
|
869
899
|
node = stack[stack.length - 1];
|
|
870
900
|
if (!node.right || last === node.right) {
|
|
@@ -885,57 +915,102 @@ export class BST<
|
|
|
885
915
|
return balanced;
|
|
886
916
|
}
|
|
887
917
|
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
918
|
+
/**
|
|
919
|
+
* Time complexity: O(n)
|
|
920
|
+
* Space complexity: O(n)
|
|
921
|
+
*
|
|
922
|
+
* The `map` function in TypeScript overrides the default map behavior for a binary search tree by
|
|
923
|
+
* applying a callback function to each entry and creating a new tree with the results.
|
|
924
|
+
* @param callback - A function that will be called for each entry in the BST. It takes four
|
|
925
|
+
* arguments: the key, the value (which can be undefined), the index of the entry, and a reference to
|
|
926
|
+
* the BST itself.
|
|
927
|
+
* @param [options] - The `options` parameter in the `override map` method is of type `BSTOptions<MK,
|
|
928
|
+
* MV, MR>`. It is an optional parameter that allows you to specify additional options for the Binary
|
|
929
|
+
* Search Tree (BST) being created in the `map` method. These options could include configuration
|
|
930
|
+
* @param {any} [thisArg] - The `thisArg` parameter in the `override map` method is used to specify
|
|
931
|
+
* the value of `this` that should be used when executing the `callback` function. It allows you to
|
|
932
|
+
* set the context or scope in which the callback function will be called. This can be useful when
|
|
933
|
+
* you want
|
|
934
|
+
* @returns The `map` method is returning a new Binary Search Tree (`BST`) instance with the entries
|
|
935
|
+
* transformed by the provided callback function.
|
|
936
|
+
*/
|
|
937
|
+
override map(
|
|
938
|
+
callback: EntryCallback<K, V | undefined, [MK, MV]>,
|
|
939
|
+
options?: BSTOptions<MK, MV, MR>,
|
|
940
|
+
thisArg?: any
|
|
941
|
+
): BST<MK, MV, MR> {
|
|
942
|
+
const newTree = new BST<MK, MV, MR>([], options);
|
|
943
|
+
let index = 0;
|
|
944
|
+
for (const [key, value] of this) {
|
|
945
|
+
newTree.add(callback.call(thisArg, key, value, index++, this));
|
|
903
946
|
}
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
};
|
|
947
|
+
return newTree;
|
|
948
|
+
}
|
|
907
949
|
|
|
908
950
|
/**
|
|
909
|
-
*
|
|
910
|
-
*
|
|
951
|
+
* Time complexity: O(n)
|
|
952
|
+
* Space complexity: O(n)
|
|
953
|
+
*
|
|
954
|
+
* The function `clone` overrides the default cloning behavior to create a deep copy of a tree
|
|
955
|
+
* structure.
|
|
956
|
+
* @returns The `cloned` object is being returned.
|
|
911
957
|
*/
|
|
912
|
-
|
|
913
|
-
|
|
958
|
+
override clone() {
|
|
959
|
+
const cloned = this.createTree();
|
|
960
|
+
this._clone(cloned);
|
|
961
|
+
return cloned;
|
|
914
962
|
}
|
|
915
963
|
|
|
916
|
-
protected _extractComparable?: (key: K) => Comparable;
|
|
917
|
-
|
|
918
964
|
/**
|
|
919
|
-
*
|
|
920
|
-
*
|
|
921
|
-
*
|
|
965
|
+
* Time Complexity: O(1)
|
|
966
|
+
* Space Complexity: O(1)
|
|
967
|
+
*
|
|
968
|
+
* The function overrides a method and converts a key, value pair or entry or raw element to a node.
|
|
969
|
+
* @param {BTNRep<K, V, BSTNode<K, V>>} keyNodeOrEntry - A variable that can be of
|
|
970
|
+
* type R or BTNRep<K, V, BSTNode<K, V>>. It represents either a key, a node, an entry, or a raw
|
|
971
|
+
* element.
|
|
972
|
+
* @param {V} [value] - The `value` parameter is an optional value of type `V`. It represents the
|
|
973
|
+
* value associated with a key in a key-value pair.
|
|
974
|
+
* @returns either a BSTNode<K, V> object or undefined.
|
|
922
975
|
*/
|
|
923
|
-
|
|
924
|
-
|
|
976
|
+
protected override _keyValueNodeOrEntryToNodeAndValue(
|
|
977
|
+
keyNodeOrEntry: BTNRep<K, V, BSTNode<K, V>>,
|
|
978
|
+
value?: V
|
|
979
|
+
): [OptNode<BSTNode<K, V>>, V | undefined] {
|
|
980
|
+
const [node, entryValue] = super._keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value);
|
|
981
|
+
if (node === null) return [undefined, undefined];
|
|
982
|
+
return [node, value ?? entryValue];
|
|
925
983
|
}
|
|
926
984
|
|
|
927
985
|
/**
|
|
986
|
+
* Time Complexity: O(1)
|
|
987
|
+
* Space Complexity: O(1)
|
|
988
|
+
*
|
|
928
989
|
* The function sets the root of a tree-like structure and updates the parent property of the new
|
|
929
990
|
* root.
|
|
930
|
-
* @param {OptNode<
|
|
991
|
+
* @param {OptNode<BSTNode<K, V>>} v - v is a parameter of type BSTNode<K, V> or undefined.
|
|
931
992
|
*/
|
|
932
|
-
protected override _setRoot(v: OptNode<
|
|
993
|
+
protected override _setRoot(v: OptNode<BSTNode<K, V>>) {
|
|
933
994
|
if (v) {
|
|
934
995
|
v.parent = undefined;
|
|
935
996
|
}
|
|
936
997
|
this._root = v;
|
|
937
998
|
}
|
|
938
999
|
|
|
1000
|
+
/**
|
|
1001
|
+
* Time Complexity: O(1)
|
|
1002
|
+
* Space Complexity: O(1)
|
|
1003
|
+
*
|
|
1004
|
+
* The _compare function compares two values using a specified comparator function and optionally
|
|
1005
|
+
* reverses the result.
|
|
1006
|
+
* @param {K} a - The parameter `a` is of type `K`, which is used as an input for comparison in the
|
|
1007
|
+
* `_compare` method.
|
|
1008
|
+
* @param {K} b - The parameter `b` in the `_compare` function is of type `K`.
|
|
1009
|
+
* @returns The `_compare` method is returning the result of the ternary expression. If `_isReverse`
|
|
1010
|
+
* is true, it returns the negation of the result of calling the `_comparator` function with
|
|
1011
|
+
* arguments `a` and `b`. If `_isReverse` is false, it returns the result of calling the
|
|
1012
|
+
* `_comparator` function with arguments `a` and `b`.
|
|
1013
|
+
*/
|
|
939
1014
|
protected _compare(a: K, b: K) {
|
|
940
1015
|
return this._isReverse ? -this._comparator(a, b) : this._comparator(a, b);
|
|
941
1016
|
}
|