red-black-tree-typed 1.53.6 → 1.54.1
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/README.md +52 -0
- package/dist/common/index.d.ts +12 -0
- package/dist/common/index.js +28 -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 -331
- package/dist/data-structures/binary-tree/avl-tree.d.ts +103 -69
- package/dist/data-structures/binary-tree/avl-tree.js +131 -71
- 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 +309 -208
- package/dist/data-structures/binary-tree/binary-tree.js +382 -300
- package/dist/data-structures/binary-tree/bst.d.ts +245 -127
- package/dist/data-structures/binary-tree/bst.js +366 -163
- 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} +181 -108
- 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 +26 -9
- package/dist/data-structures/heap/heap.js +37 -17
- package/dist/data-structures/linked-list/doubly-linked-list.d.ts +64 -19
- package/dist/data-structures/linked-list/doubly-linked-list.js +92 -31
- package/dist/data-structures/linked-list/singly-linked-list.d.ts +48 -12
- package/dist/data-structures/linked-list/singly-linked-list.js +74 -27
- 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 +111 -10
- package/dist/data-structures/trie/trie.js +123 -18
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- 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-counter.js +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 +1 -4
- package/dist/types/data-structures/binary-tree/bst.d.ts +6 -5
- package/dist/types/data-structures/binary-tree/index.d.ts +2 -0
- package/dist/types/data-structures/binary-tree/index.js +2 -0
- package/dist/types/data-structures/binary-tree/rb-tree.d.ts +2 -5
- 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/dist/types/utils/utils.d.ts +10 -6
- package/dist/utils/utils.js +4 -2
- package/package.json +2 -2
- package/src/common/index.ts +25 -0
- 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 +152 -373
- package/src/data-structures/binary-tree/avl-tree.ts +164 -106
- package/src/data-structures/binary-tree/binary-indexed-tree.ts +3 -0
- package/src/data-structures/binary-tree/binary-tree.ts +563 -447
- package/src/data-structures/binary-tree/bst.ts +433 -237
- package/src/data-structures/binary-tree/index.ts +3 -1
- package/src/data-structures/binary-tree/{rb-tree.ts → red-black-tree.ts} +224 -146
- 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 +72 -49
- package/src/data-structures/linked-list/doubly-linked-list.ts +186 -118
- package/src/data-structures/linked-list/singly-linked-list.ts +81 -28
- 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 +123 -17
- package/src/index.ts +4 -3
- 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 +1 -6
- package/src/types/data-structures/binary-tree/bst.ts +8 -7
- 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/src/types/utils/utils.ts +16 -10
- package/src/utils/utils.ts +4 -2
- package/dist/data-structures/binary-tree/rb-tree.d.ts +0 -205
- package/src/types/data-structures/binary-tree/rb-tree.ts +0 -10
|
@@ -6,79 +6,64 @@
|
|
|
6
6
|
* @license MIT License
|
|
7
7
|
*/
|
|
8
8
|
import type {
|
|
9
|
-
BSTNested,
|
|
10
|
-
BSTNodeNested,
|
|
11
9
|
BSTNOptKeyOrNode,
|
|
12
10
|
BSTOptions,
|
|
13
11
|
BTNRep,
|
|
12
|
+
Comparable,
|
|
14
13
|
Comparator,
|
|
15
14
|
CP,
|
|
16
15
|
DFSOrderPattern,
|
|
16
|
+
EntryCallback,
|
|
17
17
|
IterationType,
|
|
18
18
|
NodeCallback,
|
|
19
19
|
NodePredicate,
|
|
20
|
-
OptNode
|
|
20
|
+
OptNode,
|
|
21
|
+
OptNodeOrNull
|
|
21
22
|
} from '../../types';
|
|
22
23
|
import { BinaryTree, BinaryTreeNode } from './binary-tree';
|
|
23
24
|
import { IBinaryTree } from '../../interfaces';
|
|
24
25
|
import { Queue } from '../queue';
|
|
25
26
|
import { isComparable } from '../../utils';
|
|
27
|
+
import { Range } from '../../common';
|
|
26
28
|
|
|
27
|
-
export class BSTNode<K = any, V = any
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
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
|
+
*/
|
|
34
39
|
constructor(key: K, value?: V) {
|
|
35
40
|
super(key, value);
|
|
36
|
-
this.parent = undefined;
|
|
37
|
-
this._left = undefined;
|
|
38
|
-
this._right = undefined;
|
|
39
41
|
}
|
|
40
42
|
|
|
41
|
-
|
|
43
|
+
override parent?: BSTNode<K, V> = undefined;
|
|
42
44
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
*/
|
|
47
|
-
override get left(): OptNode<NODE> {
|
|
45
|
+
override _left?: OptNodeOrNull<BSTNode<K, V>> = undefined;
|
|
46
|
+
|
|
47
|
+
override get left(): OptNodeOrNull<BSTNode<K, V>> {
|
|
48
48
|
return this._left;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
* The function sets the left child of a node and updates the parent reference of the child.
|
|
53
|
-
* @param {OptNode<NODE>} v - The parameter `v` is of type `OptNode<NODE>`. It can either be an
|
|
54
|
-
* instance of the `NODE` class or `undefined`.
|
|
55
|
-
*/
|
|
56
|
-
override set left(v: OptNode<NODE>) {
|
|
51
|
+
override set left(v: OptNodeOrNull<BSTNode<K, V>>) {
|
|
57
52
|
if (v) {
|
|
58
|
-
v.parent = this
|
|
53
|
+
v.parent = this;
|
|
59
54
|
}
|
|
60
55
|
this._left = v;
|
|
61
56
|
}
|
|
62
57
|
|
|
63
|
-
|
|
58
|
+
override _right?: OptNodeOrNull<BSTNode<K, V>> = undefined;
|
|
64
59
|
|
|
65
|
-
|
|
66
|
-
* The function returns the right node of a binary tree or undefined if there is no right node.
|
|
67
|
-
* @returns The method is returning the value of the `_right` property, which is of type `NODE` or
|
|
68
|
-
* `undefined`.
|
|
69
|
-
*/
|
|
70
|
-
override get right(): OptNode<NODE> {
|
|
60
|
+
override get right(): OptNodeOrNull<BSTNode<K, V>> {
|
|
71
61
|
return this._right;
|
|
72
62
|
}
|
|
73
63
|
|
|
74
|
-
|
|
75
|
-
* The function sets the right child of a node and updates the parent reference of the child.
|
|
76
|
-
* @param {OptNode<NODE>} v - The parameter `v` is of type `OptNode<NODE>`. It can either be a
|
|
77
|
-
* `NODE` object or `undefined`.
|
|
78
|
-
*/
|
|
79
|
-
override set right(v: OptNode<NODE>) {
|
|
64
|
+
override set right(v: OptNodeOrNull<BSTNode<K, V>>) {
|
|
80
65
|
if (v) {
|
|
81
|
-
v.parent = this
|
|
66
|
+
v.parent = this;
|
|
82
67
|
}
|
|
83
68
|
this._right = v;
|
|
84
69
|
}
|
|
@@ -92,91 +77,164 @@ export class BSTNode<K = any, V = any, NODE extends BSTNode<K, V, NODE> = BSTNod
|
|
|
92
77
|
* 5. Logarithmic Operations: Ideal operations like insertion, deletion, and searching are O(log n) time-efficient.
|
|
93
78
|
* 6. Balance Variability: Can become unbalanced; special types maintain balance.
|
|
94
79
|
* 7. No Auto-Balancing: Standard BSTs don't automatically balance themselves.
|
|
80
|
+
* @example
|
|
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
|
+
* ]);
|
|
95
|
+
*
|
|
96
|
+
* // Merge datasets into a single BinarySearchTree
|
|
97
|
+
* const merged = new BST<number, string>(dataset1);
|
|
98
|
+
* merged.addMany(dataset2);
|
|
99
|
+
* merged.merge(dataset3);
|
|
100
|
+
*
|
|
101
|
+
* // Verify merged dataset is in sorted order
|
|
102
|
+
* console.log([...merged.values()]); // ['A', 'B', 'C', 'D', 'E', 'F', 'G']
|
|
103
|
+
* @example
|
|
104
|
+
* // Find elements in a range
|
|
105
|
+
* const bst = new BST<number>([10, 5, 15, 3, 7, 12, 18]);
|
|
106
|
+
* console.log(bst.search(new Range(5, 10))); // [10, 5, 7]
|
|
107
|
+
* console.log(bst.rangeSearch([4, 12], node => node.key.toString())); // ['10', '12', '5', '7']
|
|
108
|
+
* console.log(bst.search(new Range(4, 12, true, false))); // [10, 5, 7]
|
|
109
|
+
* console.log(bst.rangeSearch([15, 20])); // [15, 18]
|
|
110
|
+
* console.log(bst.search(new Range(15, 20, false))); // [18]
|
|
111
|
+
* @example
|
|
112
|
+
* // Find lowest common ancestor
|
|
113
|
+
* const bst = new BST<number>([20, 10, 30, 5, 15, 25, 35, 3, 7, 12, 18]);
|
|
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
|
+
*
|
|
123
|
+
* function findFirstCommon(arr1: number[], arr2: number[]): number | undefined {
|
|
124
|
+
* for (const num of arr1) {
|
|
125
|
+
* if (arr2.indexOf(num) !== -1) {
|
|
126
|
+
* return num;
|
|
127
|
+
* }
|
|
128
|
+
* }
|
|
129
|
+
* return undefined;
|
|
130
|
+
* }
|
|
131
|
+
*
|
|
132
|
+
* // Assertions
|
|
133
|
+
* console.log(findLCA(3, 10)); // 7
|
|
134
|
+
* console.log(findLCA(5, 35)); // 15
|
|
135
|
+
* console.log(findLCA(20, 30)); // 25
|
|
95
136
|
*/
|
|
96
|
-
export class BST<
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
R = object,
|
|
100
|
-
NODE extends BSTNode<K, V, NODE> = BSTNode<K, V, BSTNodeNested<K, V>>,
|
|
101
|
-
TREE extends BST<K, V, R, NODE, TREE> = BST<K, V, R, NODE, BSTNested<K, V, R, NODE>>
|
|
102
|
-
>
|
|
103
|
-
extends BinaryTree<K, V, R, NODE, TREE>
|
|
104
|
-
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>
|
|
105
140
|
{
|
|
106
141
|
/**
|
|
107
|
-
* This
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
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:
|
|
113
149
|
*/
|
|
114
|
-
constructor(keysNodesEntriesOrRaws: Iterable<
|
|
150
|
+
constructor(keysNodesEntriesOrRaws: Iterable<BTNRep<K, V, BSTNode<K, V>> | R> = [], options?: BSTOptions<K, V, R>) {
|
|
115
151
|
super([], options);
|
|
116
152
|
|
|
117
153
|
if (options) {
|
|
118
|
-
const {
|
|
119
|
-
if (
|
|
154
|
+
const { specifyComparable, isReverse } = options;
|
|
155
|
+
if (typeof specifyComparable === 'function') this._specifyComparable = specifyComparable;
|
|
156
|
+
if (isReverse !== undefined) this._isReverse = isReverse;
|
|
120
157
|
}
|
|
121
158
|
|
|
122
159
|
if (keysNodesEntriesOrRaws) this.addMany(keysNodesEntriesOrRaws);
|
|
123
160
|
}
|
|
124
161
|
|
|
125
|
-
protected override _root?:
|
|
162
|
+
protected override _root?: BSTNode<K, V> = undefined;
|
|
126
163
|
|
|
127
|
-
|
|
128
|
-
* The function returns the root node of a tree structure.
|
|
129
|
-
* @returns The `_root` property of the object, which is of type `NODE` or `undefined`.
|
|
130
|
-
*/
|
|
131
|
-
override get root(): OptNode<NODE> {
|
|
164
|
+
override get root(): OptNode<BSTNode<K, V>> {
|
|
132
165
|
return this._root;
|
|
133
166
|
}
|
|
134
167
|
|
|
168
|
+
protected _isReverse: boolean = false;
|
|
169
|
+
|
|
170
|
+
get isReverse(): boolean {
|
|
171
|
+
return this._isReverse;
|
|
172
|
+
}
|
|
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
|
+
|
|
135
204
|
/**
|
|
205
|
+
* Time Complexity: O(1)
|
|
206
|
+
* Space Complexity: O(1)
|
|
207
|
+
*
|
|
136
208
|
* The function creates a new BSTNode with the given key and value and returns it.
|
|
137
209
|
* @param {K} key - The key parameter is of type K, which represents the type of the key for the node
|
|
138
210
|
* being created.
|
|
139
211
|
* @param {V} [value] - The "value" parameter is an optional parameter of type V. It represents the
|
|
140
212
|
* value associated with the key in the node being created.
|
|
141
|
-
* @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.
|
|
142
214
|
*/
|
|
143
|
-
override createNode(key: K, value?: V):
|
|
144
|
-
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);
|
|
145
217
|
}
|
|
146
218
|
|
|
147
219
|
/**
|
|
220
|
+
* Time Complexity: O(1)
|
|
221
|
+
* Space Complexity: O(1)
|
|
222
|
+
*
|
|
148
223
|
* The function creates a new binary search tree with the specified options.
|
|
149
224
|
* @param [options] - The `options` parameter is an optional object that allows you to customize the
|
|
150
225
|
* behavior of the `createTree` method. It accepts a partial `BSTOptions` object, which has the
|
|
151
226
|
* following properties:
|
|
152
227
|
* @returns a new instance of the BST class with the provided options.
|
|
153
228
|
*/
|
|
154
|
-
override createTree(options?: BSTOptions<K, V, R>)
|
|
155
|
-
return new BST<K, V, R,
|
|
229
|
+
override createTree(options?: BSTOptions<K, V, R>) {
|
|
230
|
+
return new BST<K, V, R, MK, MV, MR>([], {
|
|
156
231
|
iterationType: this.iterationType,
|
|
157
232
|
isMapMode: this._isMapMode,
|
|
158
|
-
|
|
233
|
+
specifyComparable: this._specifyComparable,
|
|
159
234
|
toEntryFn: this._toEntryFn,
|
|
235
|
+
isReverse: this._isReverse,
|
|
160
236
|
...options
|
|
161
|
-
})
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
/**
|
|
165
|
-
* The function overrides a method and converts a key, value pair or entry or raw element to a node.
|
|
166
|
-
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - A variable that can be of
|
|
167
|
-
* type R or BTNRep<K, V, NODE>. It represents either a key, a node, an entry, or a raw
|
|
168
|
-
* element.
|
|
169
|
-
* @param {V} [value] - The `value` parameter is an optional value of type `V`. It represents the
|
|
170
|
-
* value associated with a key in a key-value pair.
|
|
171
|
-
* @returns either a NODE object or undefined.
|
|
172
|
-
*/
|
|
173
|
-
override keyValueNodeEntryRawToNodeAndValue(
|
|
174
|
-
keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R,
|
|
175
|
-
value?: V
|
|
176
|
-
): [OptNode<NODE>, V | undefined] {
|
|
177
|
-
const [node, entryValue] = super.keyValueNodeEntryRawToNodeAndValue(keyNodeEntryOrRaw, value);
|
|
178
|
-
if (node === null) return [undefined, undefined];
|
|
179
|
-
return [node, value ?? entryValue];
|
|
237
|
+
});
|
|
180
238
|
}
|
|
181
239
|
|
|
182
240
|
/**
|
|
@@ -185,8 +243,8 @@ export class BST<
|
|
|
185
243
|
*
|
|
186
244
|
* The function ensures the existence of a node in a data structure and returns it, or undefined if
|
|
187
245
|
* it doesn't exist.
|
|
188
|
-
* @param {BTNRep<K, V,
|
|
189
|
-
* `
|
|
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,
|
|
190
248
|
* entry, or raw element that needs to be ensured in the tree.
|
|
191
249
|
* @param {IterationType} [iterationType=ITERATIVE] - The `iterationType` parameter is an optional
|
|
192
250
|
* parameter that specifies the type of iteration to be used when ensuring a node. It has a default
|
|
@@ -195,48 +253,54 @@ export class BST<
|
|
|
195
253
|
* not be ensured.
|
|
196
254
|
*/
|
|
197
255
|
override ensureNode(
|
|
198
|
-
|
|
256
|
+
keyNodeOrEntry: BTNRep<K, V, BSTNode<K, V>>,
|
|
199
257
|
iterationType: IterationType = this.iterationType
|
|
200
|
-
): OptNode<
|
|
201
|
-
return super.ensureNode(
|
|
258
|
+
): OptNode<BSTNode<K, V>> {
|
|
259
|
+
return super.ensureNode(keyNodeOrEntry, iterationType) ?? undefined;
|
|
202
260
|
}
|
|
203
261
|
|
|
204
262
|
/**
|
|
263
|
+
* Time Complexity: O(1)
|
|
264
|
+
* Space Complexity: O(1)
|
|
265
|
+
*
|
|
205
266
|
* The function checks if the input is an instance of the BSTNode class.
|
|
206
|
-
* @param {BTNRep<K, V,
|
|
207
|
-
* `
|
|
208
|
-
* @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
|
|
209
270
|
* an instance of the `BSTNode` class.
|
|
210
271
|
*/
|
|
211
|
-
override isNode(
|
|
212
|
-
return
|
|
272
|
+
override isNode(keyNodeOrEntry: BTNRep<K, V, BSTNode<K, V>>): keyNodeOrEntry is BSTNode<K, V> {
|
|
273
|
+
return keyNodeOrEntry instanceof BSTNode;
|
|
213
274
|
}
|
|
214
275
|
|
|
215
276
|
/**
|
|
216
|
-
*
|
|
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.
|
|
217
281
|
* @param {any} key - The `key` parameter is a value that will be checked to determine if it is of
|
|
218
282
|
* type `K`.
|
|
219
|
-
* @returns The `override
|
|
220
|
-
* the result of the `isComparable` function with the condition `this.
|
|
283
|
+
* @returns The `override isValidKey(key: any): key is K` function is returning a boolean value based on
|
|
284
|
+
* the result of the `isComparable` function with the condition `this._compare !==
|
|
221
285
|
* this._DEFAULT_COMPARATOR`.
|
|
222
286
|
*/
|
|
223
|
-
override
|
|
224
|
-
return isComparable(key, this.
|
|
287
|
+
override isValidKey(key: any): key is K {
|
|
288
|
+
return isComparable(key, this._specifyComparable !== undefined);
|
|
225
289
|
}
|
|
226
290
|
|
|
227
291
|
/**
|
|
228
292
|
* Time Complexity: O(log n)
|
|
229
|
-
* Space Complexity: O(
|
|
293
|
+
* Space Complexity: O(log n)
|
|
230
294
|
*
|
|
231
295
|
* The `add` function in TypeScript adds a new node to a binary search tree based on the key value.
|
|
232
|
-
* @param {BTNRep<K, V,
|
|
233
|
-
* `
|
|
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>>`.
|
|
234
298
|
* @param {V} [value] - The `value` parameter is an optional value that can be associated with the
|
|
235
299
|
* key in the binary search tree. If provided, it will be stored in the node along with the key.
|
|
236
300
|
* @returns a boolean value.
|
|
237
301
|
*/
|
|
238
|
-
override add(
|
|
239
|
-
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);
|
|
240
304
|
if (newNode === undefined) return false;
|
|
241
305
|
|
|
242
306
|
if (this._root === undefined) {
|
|
@@ -248,18 +312,18 @@ export class BST<
|
|
|
248
312
|
|
|
249
313
|
let current = this._root;
|
|
250
314
|
while (current !== undefined) {
|
|
251
|
-
if (this.
|
|
315
|
+
if (this._compare(current.key, newNode.key) === 0) {
|
|
252
316
|
this._replaceNode(current, newNode);
|
|
253
317
|
if (this._isMapMode) this._setValue(current.key, newValue);
|
|
254
318
|
return true;
|
|
255
|
-
} else if (this.
|
|
319
|
+
} else if (this._compare(current.key, newNode.key) > 0) {
|
|
256
320
|
if (current.left === undefined) {
|
|
257
321
|
current.left = newNode;
|
|
258
322
|
if (this._isMapMode) this._setValue(newNode?.key, newValue);
|
|
259
323
|
this._size++;
|
|
260
324
|
return true;
|
|
261
325
|
}
|
|
262
|
-
current = current.left;
|
|
326
|
+
if (current.left !== null) current = current.left;
|
|
263
327
|
} else {
|
|
264
328
|
if (current.right === undefined) {
|
|
265
329
|
current.right = newNode;
|
|
@@ -267,7 +331,7 @@ export class BST<
|
|
|
267
331
|
this._size++;
|
|
268
332
|
return true;
|
|
269
333
|
}
|
|
270
|
-
current = current.right;
|
|
334
|
+
if (current.right !== null) current = current.right;
|
|
271
335
|
}
|
|
272
336
|
}
|
|
273
337
|
|
|
@@ -296,7 +360,7 @@ export class BST<
|
|
|
296
360
|
* successfully inserted into the data structure.
|
|
297
361
|
*/
|
|
298
362
|
override addMany(
|
|
299
|
-
keysNodesEntriesOrRaws: Iterable<R | BTNRep<K, V,
|
|
363
|
+
keysNodesEntriesOrRaws: Iterable<R | BTNRep<K, V, BSTNode<K, V>>>,
|
|
300
364
|
values?: Iterable<V | undefined>,
|
|
301
365
|
isBalanceAdd = true,
|
|
302
366
|
iterationType: IterationType = this.iterationType
|
|
@@ -310,15 +374,16 @@ export class BST<
|
|
|
310
374
|
}
|
|
311
375
|
|
|
312
376
|
if (!isBalanceAdd) {
|
|
313
|
-
for (
|
|
377
|
+
for (let kve of keysNodesEntriesOrRaws) {
|
|
314
378
|
const value = valuesIterator?.next().value;
|
|
379
|
+
if (this.isRaw(kve)) kve = this._toEntryFn!(kve);
|
|
315
380
|
inserted.push(this.add(kve, value));
|
|
316
381
|
}
|
|
317
382
|
return inserted;
|
|
318
383
|
}
|
|
319
384
|
|
|
320
385
|
const realBTNExemplars: {
|
|
321
|
-
key: R | BTNRep<K, V,
|
|
386
|
+
key: R | BTNRep<K, V, BSTNode<K, V>>;
|
|
322
387
|
value: V | undefined;
|
|
323
388
|
orgIndex: number;
|
|
324
389
|
}[] = [];
|
|
@@ -329,37 +394,41 @@ export class BST<
|
|
|
329
394
|
i++;
|
|
330
395
|
}
|
|
331
396
|
|
|
332
|
-
let sorted: { key: R | BTNRep<K, V,
|
|
397
|
+
let sorted: { key: R | BTNRep<K, V, BSTNode<K, V>>; value: V | undefined; orgIndex: number }[] = [];
|
|
333
398
|
|
|
334
399
|
sorted = realBTNExemplars.sort(({ key: a }, { key: b }) => {
|
|
335
400
|
let keyA: K | undefined | null, keyB: K | undefined | null;
|
|
336
|
-
if (this.
|
|
401
|
+
if (this.isRaw(a)) keyA = this._toEntryFn!(a)[0];
|
|
402
|
+
else if (this.isEntry(a)) keyA = a[0];
|
|
337
403
|
else if (this.isRealNode(a)) keyA = a.key;
|
|
338
|
-
else
|
|
339
|
-
keyA = this._toEntryFn(a as R)[0];
|
|
340
|
-
} else {
|
|
404
|
+
else {
|
|
341
405
|
keyA = a as K;
|
|
342
406
|
}
|
|
343
407
|
|
|
344
|
-
if (this.
|
|
408
|
+
if (this.isRaw(b)) keyB = this._toEntryFn!(b)[0];
|
|
409
|
+
else if (this.isEntry(b)) keyB = b[0];
|
|
345
410
|
else if (this.isRealNode(b)) keyB = b.key;
|
|
346
|
-
else
|
|
347
|
-
keyB = this._toEntryFn(b as R)[0];
|
|
348
|
-
} else {
|
|
411
|
+
else {
|
|
349
412
|
keyB = b as K;
|
|
350
413
|
}
|
|
351
414
|
|
|
352
415
|
if (keyA !== undefined && keyA !== null && keyB !== undefined && keyB !== null) {
|
|
353
|
-
return this.
|
|
416
|
+
return this._compare(keyA, keyB);
|
|
354
417
|
}
|
|
355
418
|
return 0;
|
|
356
419
|
});
|
|
357
420
|
|
|
358
|
-
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 }[]) => {
|
|
359
422
|
if (arr.length === 0) return;
|
|
360
423
|
|
|
361
424
|
const mid = Math.floor((arr.length - 1) / 2);
|
|
362
|
-
|
|
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
|
+
}
|
|
363
432
|
inserted[orgIndex] = this.add(key, value);
|
|
364
433
|
_dfs(arr.slice(0, mid));
|
|
365
434
|
_dfs(arr.slice(mid + 1));
|
|
@@ -374,7 +443,13 @@ export class BST<
|
|
|
374
443
|
const [l, r] = popped;
|
|
375
444
|
if (l <= r) {
|
|
376
445
|
const m = l + Math.floor((r - l) / 2);
|
|
377
|
-
|
|
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
|
+
}
|
|
378
453
|
inserted[orgIndex] = this.add(key, value);
|
|
379
454
|
stack.push([m + 1, r]);
|
|
380
455
|
stack.push([l, m - 1]);
|
|
@@ -396,60 +471,97 @@ export class BST<
|
|
|
396
471
|
* Time Complexity: O(log n)
|
|
397
472
|
* Space Complexity: O(k + log n)
|
|
398
473
|
*
|
|
399
|
-
* The function `
|
|
400
|
-
*
|
|
401
|
-
* @param {BTNRep<K, V,
|
|
402
|
-
* parameter in the `
|
|
403
|
-
*
|
|
404
|
-
*
|
|
405
|
-
*
|
|
406
|
-
*
|
|
407
|
-
*
|
|
408
|
-
*
|
|
409
|
-
*
|
|
410
|
-
*
|
|
411
|
-
*
|
|
412
|
-
*
|
|
413
|
-
*
|
|
414
|
-
*
|
|
415
|
-
*
|
|
416
|
-
*
|
|
474
|
+
* The function `search` in TypeScript overrides the search behavior in a binary tree structure based
|
|
475
|
+
* on specified criteria.
|
|
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
|
|
478
|
+
* following types:
|
|
479
|
+
* @param [onlyOne=false] - The `onlyOne` parameter is a boolean flag that determines whether the
|
|
480
|
+
* search should stop after finding the first matching node. If `onlyOne` is set to `true`, the
|
|
481
|
+
* search will return as soon as a matching node is found. If `onlyOne` is set to `false`, the
|
|
482
|
+
* @param {C} callback - The `callback` parameter in the `override search` function is a function
|
|
483
|
+
* that will be called on each node that matches the search criteria. It is of type `C`, which
|
|
484
|
+
* extends `NodeCallback<BSTNode<K, V>>`. The callback function should accept a node of type `BSTNode<K, V>` as its
|
|
485
|
+
* argument and
|
|
486
|
+
* @param {BTNRep<K, V, BSTNode<K, V>>} startNode - The `startNode` parameter in the `override search`
|
|
487
|
+
* method represents the node from which the search operation will begin. It is the starting point
|
|
488
|
+
* for searching within the tree data structure. The method ensures that the `startNode` is a valid
|
|
489
|
+
* node before proceeding with the search operation. If the `
|
|
490
|
+
* @param {IterationType} iterationType - The `iterationType` parameter in the `override search`
|
|
491
|
+
* function determines the type of iteration to be used during the search operation. It can have two
|
|
492
|
+
* possible values:
|
|
493
|
+
* @returns The `override search` method returns an array of values that match the search criteria
|
|
494
|
+
* specified by the input parameters. The method performs a search operation on a binary tree
|
|
495
|
+
* structure based on the provided key, predicate, and other options. The search results are
|
|
496
|
+
* collected in an array and returned as the output of the method.
|
|
417
497
|
*/
|
|
418
|
-
override
|
|
419
|
-
|
|
498
|
+
override search<C extends NodeCallback<BSTNode<K, V>>>(
|
|
499
|
+
keyNodeEntryOrPredicate: BTNRep<K, V, BSTNode<K, V>> | NodePredicate<BSTNode<K, V>> | Range<K>,
|
|
420
500
|
onlyOne = false,
|
|
421
|
-
|
|
501
|
+
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
502
|
+
startNode: BTNRep<K, V, BSTNode<K, V>> = this._root,
|
|
422
503
|
iterationType: IterationType = this.iterationType
|
|
423
|
-
):
|
|
424
|
-
if (
|
|
425
|
-
if (
|
|
504
|
+
): ReturnType<C>[] {
|
|
505
|
+
if (keyNodeEntryOrPredicate === undefined) return [];
|
|
506
|
+
if (keyNodeEntryOrPredicate === null) return [];
|
|
426
507
|
startNode = this.ensureNode(startNode);
|
|
427
508
|
if (!startNode) return [];
|
|
428
|
-
|
|
429
|
-
const ans: NODE[] = [];
|
|
509
|
+
let predicate: NodePredicate<BSTNode<K, V>>;
|
|
430
510
|
|
|
511
|
+
const isRange = this.isRange(keyNodeEntryOrPredicate);
|
|
512
|
+
// Set predicate based on parameter type
|
|
513
|
+
if (isRange) {
|
|
514
|
+
predicate = node => keyNodeEntryOrPredicate.isInRange(node.key, this._comparator);
|
|
515
|
+
} else {
|
|
516
|
+
predicate = this._ensurePredicate(keyNodeEntryOrPredicate);
|
|
517
|
+
}
|
|
518
|
+
const isToLeftByRange = (cur: BSTNode<K, V>) => {
|
|
519
|
+
if (isRange) {
|
|
520
|
+
const range = keyNodeEntryOrPredicate;
|
|
521
|
+
const leftS = this.isReverse ? range.high : range.low;
|
|
522
|
+
const leftI = this.isReverse ? range.includeHigh : range.includeLow;
|
|
523
|
+
return (leftI && this._compare(cur.key, leftS) >= 0) || (!leftI && this._compare(cur.key, leftS) > 0);
|
|
524
|
+
}
|
|
525
|
+
return false;
|
|
526
|
+
};
|
|
527
|
+
|
|
528
|
+
const isToRightByRange = (cur: BSTNode<K, V>) => {
|
|
529
|
+
if (isRange) {
|
|
530
|
+
const range = keyNodeEntryOrPredicate;
|
|
531
|
+
const rightS = this.isReverse ? range.low : range.high;
|
|
532
|
+
const rightI = this.isReverse ? range.includeLow : range.includeLow;
|
|
533
|
+
|
|
534
|
+
return (rightI && this._compare(cur.key, rightS) <= 0) || (!rightI && this._compare(cur.key, rightS) < 0);
|
|
535
|
+
}
|
|
536
|
+
return false;
|
|
537
|
+
};
|
|
538
|
+
const ans: ReturnType<C>[] = [];
|
|
431
539
|
if (iterationType === 'RECURSIVE') {
|
|
432
|
-
const dfs = (cur:
|
|
433
|
-
if (
|
|
434
|
-
ans.push(cur);
|
|
540
|
+
const dfs = (cur: BSTNode<K, V>) => {
|
|
541
|
+
if (predicate(cur)) {
|
|
542
|
+
ans.push(callback(cur));
|
|
435
543
|
if (onlyOne) return;
|
|
436
544
|
}
|
|
437
545
|
|
|
438
546
|
if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right)) return;
|
|
439
|
-
|
|
440
|
-
|
|
547
|
+
|
|
548
|
+
if (isRange) {
|
|
549
|
+
if (this.isRealNode(cur.left) && isToLeftByRange(cur)) dfs(cur.left);
|
|
550
|
+
if (this.isRealNode(cur.right) && isToRightByRange(cur)) dfs(cur.right);
|
|
551
|
+
} else if (!this._isPredicate(keyNodeEntryOrPredicate)) {
|
|
552
|
+
const benchmarkKey = this._extractKey(keyNodeEntryOrPredicate);
|
|
441
553
|
if (
|
|
442
554
|
this.isRealNode(cur.left) &&
|
|
443
555
|
benchmarkKey !== null &&
|
|
444
556
|
benchmarkKey !== undefined &&
|
|
445
|
-
this.
|
|
557
|
+
this._compare(cur.key, benchmarkKey) > 0
|
|
446
558
|
)
|
|
447
559
|
dfs(cur.left);
|
|
448
560
|
if (
|
|
449
561
|
this.isRealNode(cur.right) &&
|
|
450
562
|
benchmarkKey !== null &&
|
|
451
563
|
benchmarkKey !== undefined &&
|
|
452
|
-
this.
|
|
564
|
+
this._compare(cur.key, benchmarkKey) < 0
|
|
453
565
|
)
|
|
454
566
|
dfs(cur.right);
|
|
455
567
|
} else {
|
|
@@ -463,24 +575,27 @@ export class BST<
|
|
|
463
575
|
const stack = [startNode];
|
|
464
576
|
while (stack.length > 0) {
|
|
465
577
|
const cur = stack.pop()!;
|
|
466
|
-
if (
|
|
467
|
-
ans.push(cur);
|
|
578
|
+
if (predicate(cur)) {
|
|
579
|
+
ans.push(callback(cur));
|
|
468
580
|
if (onlyOne) return ans;
|
|
469
581
|
}
|
|
470
|
-
if (
|
|
471
|
-
|
|
582
|
+
if (isRange) {
|
|
583
|
+
if (this.isRealNode(cur.left) && isToLeftByRange(cur)) stack.push(cur.left);
|
|
584
|
+
if (this.isRealNode(cur.right) && isToRightByRange(cur)) stack.push(cur.right);
|
|
585
|
+
} else if (!this._isPredicate(keyNodeEntryOrPredicate)) {
|
|
586
|
+
const benchmarkKey = this._extractKey(keyNodeEntryOrPredicate);
|
|
472
587
|
if (
|
|
473
588
|
this.isRealNode(cur.right) &&
|
|
474
589
|
benchmarkKey !== null &&
|
|
475
590
|
benchmarkKey !== undefined &&
|
|
476
|
-
this.
|
|
591
|
+
this._compare(cur.key, benchmarkKey) < 0
|
|
477
592
|
)
|
|
478
593
|
stack.push(cur.right);
|
|
479
594
|
if (
|
|
480
595
|
this.isRealNode(cur.left) &&
|
|
481
596
|
benchmarkKey !== null &&
|
|
482
597
|
benchmarkKey !== undefined &&
|
|
483
|
-
this.
|
|
598
|
+
this._compare(cur.key, benchmarkKey) > 0
|
|
484
599
|
)
|
|
485
600
|
stack.push(cur.left);
|
|
486
601
|
} else {
|
|
@@ -495,12 +610,43 @@ export class BST<
|
|
|
495
610
|
|
|
496
611
|
/**
|
|
497
612
|
* Time Complexity: O(log n)
|
|
498
|
-
* 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)
|
|
499
645
|
*
|
|
500
|
-
* This function retrieves a node based on a given
|
|
501
|
-
* @param {BTNRep<K, V,
|
|
502
|
-
* parameter can be of type `BTNRep<K, V,
|
|
503
|
-
* @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
|
|
504
650
|
* is used to specify the starting point for searching nodes in the binary search tree. If no
|
|
505
651
|
* specific starting point is provided, the default value is set to `this._root`, which is the root
|
|
506
652
|
* node of the binary search tree.
|
|
@@ -508,34 +654,17 @@ export class BST<
|
|
|
508
654
|
* parameter that specifies the type of iteration to be used. It has a default value of
|
|
509
655
|
* `this.iterationType`, which means it will use the iteration type defined in the class instance if
|
|
510
656
|
* no value is provided when calling the method.
|
|
511
|
-
* @returns The `getNode` method is returning an optional binary search tree node (`OptNode<
|
|
512
|
-
* 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
|
|
513
659
|
* the specified root node (`startNode`) and using the specified iteration type. The method then
|
|
514
660
|
* returns the first node found or `undefined` if no node is found.
|
|
515
661
|
*/
|
|
516
662
|
override getNode(
|
|
517
|
-
|
|
518
|
-
startNode:
|
|
663
|
+
keyNodeEntryOrPredicate: BTNRep<K, V, BSTNode<K, V>> | NodePredicate<BSTNode<K, V>>,
|
|
664
|
+
startNode: BSTNOptKeyOrNode<K, BSTNode<K, V>> = this._root,
|
|
519
665
|
iterationType: IterationType = this.iterationType
|
|
520
|
-
): OptNode<
|
|
521
|
-
return this.getNodes(
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
/**
|
|
525
|
-
* Time Complexity: O(log n)
|
|
526
|
-
* Space Complexity: O(1)
|
|
527
|
-
*
|
|
528
|
-
* The function `getNodeByKey` returns a node with a specific key from a tree data structure.
|
|
529
|
-
* @param {K} key - The key parameter is the value used to search for a specific node in the tree. It
|
|
530
|
-
* is typically a unique identifier or a value that can be used to determine the position of the node
|
|
531
|
-
* in the tree structure.
|
|
532
|
-
* @param {IterationType} [iterationType=ITERATIVE] - The `iterationType` parameter is an optional
|
|
533
|
-
* parameter that specifies the type of iteration to be used when searching for a node in the tree.
|
|
534
|
-
* It has a default value of `'ITERATIVE'`.
|
|
535
|
-
* @returns The method is returning a NODE object or undefined.
|
|
536
|
-
*/
|
|
537
|
-
override getNodeByKey(key: K, iterationType: IterationType = this.iterationType): OptNode<NODE> {
|
|
538
|
-
return this.getNode(key, this._root, iterationType);
|
|
666
|
+
): OptNode<BSTNode<K, V>> {
|
|
667
|
+
return this.getNodes(keyNodeEntryOrPredicate, true, startNode, iterationType)[0] ?? undefined;
|
|
539
668
|
}
|
|
540
669
|
|
|
541
670
|
/**
|
|
@@ -550,7 +679,7 @@ export class BST<
|
|
|
550
679
|
* @param {DFSOrderPattern} [pattern=IN] - The "pattern" parameter in the code snippet refers to the
|
|
551
680
|
* order in which the Depth-First Search (DFS) algorithm visits the nodes in a tree or graph. It can
|
|
552
681
|
* take one of the following values:
|
|
553
|
-
* @param {BTNRep<K, V,
|
|
682
|
+
* @param {BTNRep<K, V, BSTNode<K, V>>} startNode - The `startNode` parameter is the starting
|
|
554
683
|
* point for the depth-first search traversal. It can be either a root node, a key-value pair, or a
|
|
555
684
|
* node entry. If not specified, the default value is the root of the tree.
|
|
556
685
|
* @param {IterationType} [iterationType=ITERATIVE] - The `iterationType` parameter specifies the
|
|
@@ -558,10 +687,10 @@ export class BST<
|
|
|
558
687
|
* following values:
|
|
559
688
|
* @returns The method is returning an array of the return type of the callback function.
|
|
560
689
|
*/
|
|
561
|
-
override dfs<C extends NodeCallback<
|
|
690
|
+
override dfs<C extends NodeCallback<BSTNode<K, V>>>(
|
|
562
691
|
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
563
692
|
pattern: DFSOrderPattern = 'IN',
|
|
564
|
-
startNode: BTNRep<K, V,
|
|
693
|
+
startNode: BTNRep<K, V, BSTNode<K, V>> = this._root,
|
|
565
694
|
iterationType: IterationType = this.iterationType
|
|
566
695
|
): ReturnType<C>[] {
|
|
567
696
|
return super.dfs(callback, pattern, startNode, iterationType);
|
|
@@ -576,7 +705,7 @@ export class BST<
|
|
|
576
705
|
* @param {C} callback - The `callback` parameter is a function that will be called for each node
|
|
577
706
|
* visited during the breadth-first search. It should take a single argument, which is the current
|
|
578
707
|
* node being visited, and it can return a value of any type.
|
|
579
|
-
* @param {BTNRep<K, V,
|
|
708
|
+
* @param {BTNRep<K, V, BSTNode<K, V>>} startNode - The `startNode` parameter is the starting
|
|
580
709
|
* point for the breadth-first search. It can be either a root node, a key-value pair, or an entry
|
|
581
710
|
* object. If no value is provided, the default value is the root of the tree.
|
|
582
711
|
* @param {IterationType} iterationType - The `iterationType` parameter is used to specify the type
|
|
@@ -584,9 +713,9 @@ export class BST<
|
|
|
584
713
|
* the following values:
|
|
585
714
|
* @returns an array of the return type of the callback function.
|
|
586
715
|
*/
|
|
587
|
-
override bfs<C extends NodeCallback<
|
|
716
|
+
override bfs<C extends NodeCallback<BSTNode<K, V>>>(
|
|
588
717
|
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
589
|
-
startNode: BTNRep<K, V,
|
|
718
|
+
startNode: BTNRep<K, V, BSTNode<K, V>> = this._root,
|
|
590
719
|
iterationType: IterationType = this.iterationType
|
|
591
720
|
): ReturnType<C>[] {
|
|
592
721
|
return super.bfs(callback, startNode, iterationType, false);
|
|
@@ -599,9 +728,9 @@ export class BST<
|
|
|
599
728
|
* The function overrides the listLevels method from the superclass and returns an array of arrays
|
|
600
729
|
* containing the results of the callback function applied to each level of the tree.
|
|
601
730
|
* @param {C} callback - The `callback` parameter is a generic type `C` that extends
|
|
602
|
-
* `NodeCallback<
|
|
731
|
+
* `NodeCallback<BSTNode<K, V>>`. It represents a callback function that will be called for each node in the
|
|
603
732
|
* tree during the iteration process.
|
|
604
|
-
* @param {BTNRep<K, V,
|
|
733
|
+
* @param {BTNRep<K, V, BSTNode<K, V>>} startNode - The `startNode` parameter is the starting
|
|
605
734
|
* point for listing the levels of the binary tree. It can be either a root node of the tree, a
|
|
606
735
|
* key-value pair representing a node in the tree, or a key representing a node in the tree. If no
|
|
607
736
|
* value is provided, the root of
|
|
@@ -610,9 +739,9 @@ export class BST<
|
|
|
610
739
|
* @returns The method is returning a two-dimensional array of the return type of the callback
|
|
611
740
|
* function.
|
|
612
741
|
*/
|
|
613
|
-
override listLevels<C extends NodeCallback<
|
|
742
|
+
override listLevels<C extends NodeCallback<BSTNode<K, V>>>(
|
|
614
743
|
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
615
|
-
startNode: BTNRep<K, V,
|
|
744
|
+
startNode: BTNRep<K, V, BSTNode<K, V>> = this._root,
|
|
616
745
|
iterationType: IterationType = this.iterationType
|
|
617
746
|
): ReturnType<C>[][] {
|
|
618
747
|
return super.listLevels(callback, startNode, iterationType, false);
|
|
@@ -630,7 +759,7 @@ export class BST<
|
|
|
630
759
|
* @param {CP} lesserOrGreater - The `lesserOrGreater` parameter is used to determine whether to
|
|
631
760
|
* traverse nodes that are lesser, greater, or both than the `targetNode`. It accepts the values -1,
|
|
632
761
|
* 0, or 1, where:
|
|
633
|
-
* @param {BTNRep<K, V,
|
|
762
|
+
* @param {BTNRep<K, V, BSTNode<K, V>>} targetNode - The `targetNode` parameter is the node in
|
|
634
763
|
* the binary tree that you want to start traversing from. It can be specified either by providing
|
|
635
764
|
* the key of the node, the node itself, or an entry containing the key and value of the node. If no
|
|
636
765
|
* `targetNode` is provided,
|
|
@@ -639,24 +768,24 @@ export class BST<
|
|
|
639
768
|
* @returns The function `lesserOrGreaterTraverse` returns an array of values of type
|
|
640
769
|
* `ReturnType<C>`, which is the return type of the callback function passed as an argument.
|
|
641
770
|
*/
|
|
642
|
-
lesserOrGreaterTraverse<C extends NodeCallback<
|
|
771
|
+
lesserOrGreaterTraverse<C extends NodeCallback<BSTNode<K, V>>>(
|
|
643
772
|
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
644
773
|
lesserOrGreater: CP = -1,
|
|
645
|
-
targetNode: BTNRep<K, V,
|
|
774
|
+
targetNode: BTNRep<K, V, BSTNode<K, V>> = this._root,
|
|
646
775
|
iterationType: IterationType = this.iterationType
|
|
647
776
|
): ReturnType<C>[] {
|
|
648
777
|
const targetNodeEnsured = this.ensureNode(targetNode);
|
|
649
|
-
const ans: ReturnType<NodeCallback<
|
|
778
|
+
const ans: ReturnType<NodeCallback<BSTNode<K, V>>>[] = [];
|
|
650
779
|
if (!this._root) return ans;
|
|
651
780
|
if (!targetNodeEnsured) return ans;
|
|
652
781
|
|
|
653
782
|
const targetKey = targetNodeEnsured.key;
|
|
654
783
|
|
|
655
784
|
if (iterationType === 'RECURSIVE') {
|
|
656
|
-
const dfs = (cur:
|
|
657
|
-
const compared = this.
|
|
785
|
+
const dfs = (cur: BSTNode<K, V>) => {
|
|
786
|
+
const compared = this._compare(cur.key, targetKey);
|
|
658
787
|
if (Math.sign(compared) === lesserOrGreater) ans.push(callback(cur));
|
|
659
|
-
|
|
788
|
+
// TODO here can be optimized to O(log n)
|
|
660
789
|
if (this.isRealNode(cur.left)) dfs(cur.left);
|
|
661
790
|
if (this.isRealNode(cur.right)) dfs(cur.right);
|
|
662
791
|
};
|
|
@@ -664,11 +793,11 @@ export class BST<
|
|
|
664
793
|
dfs(this._root);
|
|
665
794
|
return ans;
|
|
666
795
|
} else {
|
|
667
|
-
const queue = new Queue<
|
|
796
|
+
const queue = new Queue<BSTNode<K, V>>([this._root]);
|
|
668
797
|
while (queue.size > 0) {
|
|
669
798
|
const cur = queue.shift();
|
|
670
799
|
if (this.isRealNode(cur)) {
|
|
671
|
-
const compared = this.
|
|
800
|
+
const compared = this._compare(cur.key, targetKey);
|
|
672
801
|
if (Math.sign(compared) === lesserOrGreater) ans.push(callback(cur));
|
|
673
802
|
|
|
674
803
|
if (this.isRealNode(cur.left)) queue.push(cur.left);
|
|
@@ -748,7 +877,7 @@ export class BST<
|
|
|
748
877
|
let balanced = true;
|
|
749
878
|
|
|
750
879
|
if (iterationType === 'RECURSIVE') {
|
|
751
|
-
const _height = (cur:
|
|
880
|
+
const _height = (cur: OptNodeOrNull<BSTNode<K, V>>): number => {
|
|
752
881
|
if (!cur) return 0;
|
|
753
882
|
const leftHeight = _height(cur.left),
|
|
754
883
|
rightHeight = _height(cur.right);
|
|
@@ -757,15 +886,15 @@ export class BST<
|
|
|
757
886
|
};
|
|
758
887
|
_height(this._root);
|
|
759
888
|
} else {
|
|
760
|
-
const stack:
|
|
761
|
-
let node: OptNode<
|
|
762
|
-
last: OptNode<
|
|
763
|
-
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();
|
|
764
893
|
|
|
765
894
|
while (stack.length > 0 || node) {
|
|
766
895
|
if (node) {
|
|
767
896
|
stack.push(node);
|
|
768
|
-
node = node.left;
|
|
897
|
+
if (node.left !== null) node = node.left;
|
|
769
898
|
} else {
|
|
770
899
|
node = stack[stack.length - 1];
|
|
771
900
|
if (!node.right || last === node.right) {
|
|
@@ -786,36 +915,103 @@ export class BST<
|
|
|
786
915
|
return balanced;
|
|
787
916
|
}
|
|
788
917
|
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
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));
|
|
794
946
|
}
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
return 0;
|
|
798
|
-
};
|
|
947
|
+
return newTree;
|
|
948
|
+
}
|
|
799
949
|
|
|
800
|
-
|
|
950
|
+
/**
|
|
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.
|
|
957
|
+
*/
|
|
958
|
+
override clone() {
|
|
959
|
+
const cloned = this.createTree();
|
|
960
|
+
this._clone(cloned);
|
|
961
|
+
return cloned;
|
|
962
|
+
}
|
|
801
963
|
|
|
802
964
|
/**
|
|
803
|
-
*
|
|
804
|
-
*
|
|
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.
|
|
805
975
|
*/
|
|
806
|
-
|
|
807
|
-
|
|
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];
|
|
808
983
|
}
|
|
809
984
|
|
|
810
985
|
/**
|
|
986
|
+
* Time Complexity: O(1)
|
|
987
|
+
* Space Complexity: O(1)
|
|
988
|
+
*
|
|
811
989
|
* The function sets the root of a tree-like structure and updates the parent property of the new
|
|
812
990
|
* root.
|
|
813
|
-
* @param {OptNode<
|
|
991
|
+
* @param {OptNode<BSTNode<K, V>>} v - v is a parameter of type BSTNode<K, V> or undefined.
|
|
814
992
|
*/
|
|
815
|
-
protected override _setRoot(v: OptNode<
|
|
993
|
+
protected override _setRoot(v: OptNode<BSTNode<K, V>>) {
|
|
816
994
|
if (v) {
|
|
817
995
|
v.parent = undefined;
|
|
818
996
|
}
|
|
819
997
|
this._root = v;
|
|
820
998
|
}
|
|
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
|
+
*/
|
|
1014
|
+
protected _compare(a: K, b: K) {
|
|
1015
|
+
return this._isReverse ? -this._comparator(a, b) : this._comparator(a, b);
|
|
1016
|
+
}
|
|
821
1017
|
}
|