red-black-tree-typed 2.2.2 → 2.2.3
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 +92 -37
- package/dist/cjs/index.cjs +163 -0
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs-legacy/index.cjs +164 -0
- package/dist/cjs-legacy/index.cjs.map +1 -1
- package/dist/esm/index.mjs +163 -0
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm-legacy/index.mjs +164 -0
- package/dist/esm-legacy/index.mjs.map +1 -1
- package/dist/types/data-structures/binary-tree/avl-tree.d.ts +96 -2
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +103 -7
- package/dist/types/data-structures/binary-tree/bst.d.ts +156 -13
- package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +84 -35
- package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +2 -2
- package/dist/types/data-structures/graph/directed-graph.d.ts +126 -1
- package/dist/types/data-structures/graph/undirected-graph.d.ts +160 -1
- package/dist/types/data-structures/hash/hash-map.d.ts +110 -27
- package/dist/types/data-structures/heap/heap.d.ts +107 -58
- package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +72 -404
- package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +121 -5
- package/dist/types/data-structures/queue/deque.d.ts +95 -67
- package/dist/types/data-structures/queue/queue.d.ts +90 -34
- package/dist/types/data-structures/stack/stack.d.ts +58 -40
- package/dist/types/data-structures/trie/trie.d.ts +109 -47
- package/dist/types/interfaces/binary-tree.d.ts +1 -0
- package/dist/umd/red-black-tree-typed.js +164 -0
- package/dist/umd/red-black-tree-typed.js.map +1 -1
- package/dist/umd/red-black-tree-typed.min.js +3 -3
- package/dist/umd/red-black-tree-typed.min.js.map +1 -1
- package/package.json +2 -2
- package/src/data-structures/binary-tree/avl-tree.ts +96 -2
- package/src/data-structures/binary-tree/binary-tree.ts +117 -7
- package/src/data-structures/binary-tree/bst.ts +322 -13
- package/src/data-structures/binary-tree/red-black-tree.ts +84 -35
- package/src/data-structures/binary-tree/tree-multi-map.ts +2 -2
- package/src/data-structures/graph/directed-graph.ts +126 -1
- package/src/data-structures/graph/undirected-graph.ts +160 -1
- package/src/data-structures/hash/hash-map.ts +110 -27
- package/src/data-structures/heap/heap.ts +107 -58
- package/src/data-structures/linked-list/doubly-linked-list.ts +72 -404
- package/src/data-structures/linked-list/singly-linked-list.ts +121 -5
- package/src/data-structures/queue/deque.ts +95 -67
- package/src/data-structures/queue/queue.ts +90 -34
- package/src/data-structures/stack/stack.ts +58 -40
- package/src/data-structures/trie/trie.ts +109 -47
- package/src/interfaces/binary-tree.ts +2 -0
|
@@ -128,8 +128,102 @@ export declare class AVLTreeNode<K = any, V = any> {
|
|
|
128
128
|
* 7. Path Length: The path length from the root to any leaf is longer compared to an unbalanced BST, but shorter than a linear chain of nodes.
|
|
129
129
|
*
|
|
130
130
|
* @example
|
|
131
|
+
* // basic AVLTree creation and add operation
|
|
132
|
+
* // Create a simple AVLTree with initial values
|
|
133
|
+
* const tree = new AVLTree([5, 2, 8, 1, 9]);
|
|
134
|
+
*
|
|
135
|
+
* tree.print();
|
|
136
|
+
* // _2___
|
|
137
|
+
* // / \
|
|
138
|
+
* // 1 _8_
|
|
139
|
+
* // / \
|
|
140
|
+
* // 5 9
|
|
141
|
+
*
|
|
142
|
+
* // Verify the tree maintains sorted order
|
|
143
|
+
* console.log([...tree.keys()]); // [1, 2, 5, 8, 9];
|
|
144
|
+
*
|
|
145
|
+
* // Check size
|
|
146
|
+
* console.log(tree.size); // 5;
|
|
147
|
+
*
|
|
148
|
+
* // Add a new element
|
|
149
|
+
* tree.add(3);
|
|
150
|
+
* console.log(tree.size); // 6;
|
|
151
|
+
* console.log([...tree.keys()]); // [1, 2, 3, 5, 8, 9];
|
|
152
|
+
* @example
|
|
153
|
+
* // AVLTree has and get operations
|
|
154
|
+
* const tree = new AVLTree<number>([11, 3, 15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5]);
|
|
155
|
+
*
|
|
156
|
+
* // Check if element exists
|
|
157
|
+
* console.log(tree.has(6)); // true;
|
|
158
|
+
* console.log(tree.has(99)); // false;
|
|
159
|
+
*
|
|
160
|
+
* // Get node by key
|
|
161
|
+
* const node = tree.getNode(6);
|
|
162
|
+
* console.log(node?.key); // 6;
|
|
163
|
+
*
|
|
164
|
+
* // Verify tree is balanced
|
|
165
|
+
* console.log(tree.isAVLBalanced()); // true;
|
|
166
|
+
* @example
|
|
167
|
+
* // AVLTree delete and balance verification
|
|
168
|
+
* const tree = new AVLTree([11, 3, 15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5]);
|
|
169
|
+
*
|
|
170
|
+
* // Delete an element
|
|
171
|
+
* tree.delete(10);
|
|
172
|
+
* console.log(tree.has(10)); // false;
|
|
173
|
+
*
|
|
174
|
+
* // Tree should remain balanced after deletion
|
|
175
|
+
* console.log(tree.isAVLBalanced()); // true;
|
|
176
|
+
*
|
|
177
|
+
* // Size decreased
|
|
178
|
+
* console.log(tree.size); // 15;
|
|
179
|
+
*
|
|
180
|
+
* // Remaining elements are still sorted
|
|
181
|
+
* const keys = [...tree.keys()];
|
|
182
|
+
* console.log(keys); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15, 16];
|
|
183
|
+
* @example
|
|
184
|
+
* // AVLTree for university ranking system with strict balance
|
|
185
|
+
* interface University {
|
|
186
|
+
* name: string;
|
|
187
|
+
* rank: number;
|
|
188
|
+
* students: number;
|
|
189
|
+
* }
|
|
190
|
+
*
|
|
191
|
+
* // AVLTree provides highest search efficiency with strict balance
|
|
192
|
+
* // (every node's left/right subtrees differ by at most 1 in height)
|
|
193
|
+
* const universityTree = new AVLTree<number, University>([
|
|
194
|
+
* [1, { name: 'MIT', rank: 1, students: 1200 }],
|
|
195
|
+
* [5, { name: 'Stanford', rank: 5, students: 1800 }],
|
|
196
|
+
* [3, { name: 'Harvard', rank: 3, students: 2300 }],
|
|
197
|
+
* [2, { name: 'Caltech', rank: 2, students: 400 }],
|
|
198
|
+
* [4, { name: 'CMU', rank: 4, students: 1500 }]
|
|
199
|
+
* ]);
|
|
200
|
+
*
|
|
201
|
+
* // Quick lookup by rank
|
|
202
|
+
* const mit = universityTree.get(1);
|
|
203
|
+
* console.log(mit?.name); // 'MIT';
|
|
204
|
+
*
|
|
205
|
+
* const cmulevel = universityTree.getHeight(4);
|
|
206
|
+
* console.log(typeof cmulevel); // 'number';
|
|
207
|
+
*
|
|
208
|
+
* // Tree maintains strict balance during insertions and deletions
|
|
209
|
+
* console.log(universityTree.isAVLBalanced()); // true;
|
|
210
|
+
*
|
|
211
|
+
* // Add more universities
|
|
212
|
+
* universityTree.add(6, { name: 'Oxford', rank: 6, students: 2000 });
|
|
213
|
+
* console.log(universityTree.isAVLBalanced()); // true;
|
|
214
|
+
*
|
|
215
|
+
* // Delete and verify balance is maintained
|
|
216
|
+
* universityTree.delete(2);
|
|
217
|
+
* console.log(universityTree.has(2)); // false;
|
|
218
|
+
* console.log(universityTree.isAVLBalanced()); // true;
|
|
219
|
+
*
|
|
220
|
+
* // Get all remaining universities in rank order
|
|
221
|
+
* const remainingRanks = [...universityTree.keys()];
|
|
222
|
+
* console.log(remainingRanks); // [1, 3, 4, 5, 6];
|
|
223
|
+
* console.log(universityTree.size); // 5;
|
|
224
|
+
* @example
|
|
131
225
|
* // Find elements in a range
|
|
132
|
-
*
|
|
226
|
+
* // In interval queries, AVL trees, with their strictly balanced structure and lower height, offer better query efficiency, making them ideal for frequent and high-performance interval queries. In contrast, Red-Black trees, with lower update costs, are more suitable for scenarios involving frequent insertions and deletions where the requirements for interval queries are less demanding.
|
|
133
227
|
* type Datum = { timestamp: Date; temperature: number };
|
|
134
228
|
* // Fixed dataset of CPU temperature readings
|
|
135
229
|
* const cpuData: Datum[] = [
|
|
@@ -190,7 +284,7 @@ export declare class AVLTreeNode<K = any, V = any> {
|
|
|
190
284
|
* // { minute: 13, temperature: 60.2 },
|
|
191
285
|
* // { minute: 14, temperature: 59.8 },
|
|
192
286
|
* // { minute: 15, temperature: 58.6 }
|
|
193
|
-
* // ]
|
|
287
|
+
* // ];
|
|
194
288
|
*/
|
|
195
289
|
export declare class AVLTree<K = any, V = any, R = any> extends BST<K, V, R> implements IBinaryTree<K, V, R> {
|
|
196
290
|
/**
|
|
@@ -125,8 +125,86 @@ export declare class BinaryTreeNode<K = any, V = any> {
|
|
|
125
125
|
* 5. Leaf Nodes: Nodes without children are leaves.
|
|
126
126
|
*
|
|
127
127
|
* @example
|
|
128
|
+
* // basic BinaryTree creation and insertion
|
|
129
|
+
* // Create a BinaryTree with entries
|
|
130
|
+
* const entries: [number, string][] = [
|
|
131
|
+
* [6, 'six'],
|
|
132
|
+
* [1, 'one'],
|
|
133
|
+
* [2, 'two'],
|
|
134
|
+
* [7, 'seven'],
|
|
135
|
+
* [5, 'five'],
|
|
136
|
+
* [3, 'three'],
|
|
137
|
+
* [4, 'four'],
|
|
138
|
+
* [9, 'nine'],
|
|
139
|
+
* [8, 'eight']
|
|
140
|
+
* ];
|
|
141
|
+
*
|
|
142
|
+
* const tree = new BinaryTree(entries);
|
|
143
|
+
*
|
|
144
|
+
* // Verify size
|
|
145
|
+
* console.log(tree.size); // 9;
|
|
146
|
+
*
|
|
147
|
+
* // Add new element
|
|
148
|
+
* tree.add(10, 'ten');
|
|
149
|
+
* console.log(tree.size); // 10;
|
|
150
|
+
* @example
|
|
151
|
+
* // BinaryTree get and has operations
|
|
152
|
+
* const tree = new BinaryTree(
|
|
153
|
+
* [
|
|
154
|
+
* [5, 'five'],
|
|
155
|
+
* [3, 'three'],
|
|
156
|
+
* [7, 'seven'],
|
|
157
|
+
* [1, 'one'],
|
|
158
|
+
* [4, 'four'],
|
|
159
|
+
* [6, 'six'],
|
|
160
|
+
* [8, 'eight']
|
|
161
|
+
* ],
|
|
162
|
+
* { isMapMode: false }
|
|
163
|
+
* );
|
|
164
|
+
*
|
|
165
|
+
* // Check if key exists
|
|
166
|
+
* console.log(tree.has(5)); // true;
|
|
167
|
+
* console.log(tree.has(10)); // false;
|
|
168
|
+
*
|
|
169
|
+
* // Get value by key
|
|
170
|
+
* console.log(tree.get(3)); // 'three';
|
|
171
|
+
* console.log(tree.get(7)); // 'seven';
|
|
172
|
+
* console.log(tree.get(100)); // undefined;
|
|
173
|
+
*
|
|
174
|
+
* // Get node structure
|
|
175
|
+
* const node = tree.getNode(5);
|
|
176
|
+
* console.log(node?.key); // 5;
|
|
177
|
+
* console.log(node?.value); // 'five';
|
|
178
|
+
* @example
|
|
179
|
+
* // BinaryTree level-order traversal
|
|
180
|
+
* const tree = new BinaryTree([
|
|
181
|
+
* [1, 'one'],
|
|
182
|
+
* [2, 'two'],
|
|
183
|
+
* [3, 'three'],
|
|
184
|
+
* [4, 'four'],
|
|
185
|
+
* [5, 'five'],
|
|
186
|
+
* [6, 'six'],
|
|
187
|
+
* [7, 'seven']
|
|
188
|
+
* ]);
|
|
189
|
+
*
|
|
190
|
+
* // Binary tree maintains level-order insertion
|
|
191
|
+
* // Complete binary tree structure
|
|
192
|
+
* console.log(tree.size); // 7;
|
|
193
|
+
*
|
|
194
|
+
* // Verify all keys are present
|
|
195
|
+
* console.log(tree.has(1)); // true;
|
|
196
|
+
* console.log(tree.has(4)); // true;
|
|
197
|
+
* console.log(tree.has(7)); // true;
|
|
198
|
+
*
|
|
199
|
+
* // Iterate through tree
|
|
200
|
+
* const keys: number[] = [];
|
|
201
|
+
* for (const [key] of tree) {
|
|
202
|
+
* keys.push(key);
|
|
203
|
+
* }
|
|
204
|
+
* console.log(keys.length); // 7;
|
|
205
|
+
* @example
|
|
128
206
|
* // determine loan approval using a decision tree
|
|
129
|
-
*
|
|
207
|
+
* // Decision tree structure
|
|
130
208
|
* const loanDecisionTree = new BinaryTree<string>(
|
|
131
209
|
* ['stableIncome', 'goodCredit', 'Rejected', 'Approved', 'Rejected'],
|
|
132
210
|
* { isDuplicate: true }
|
|
@@ -148,19 +226,19 @@ export declare class BinaryTreeNode<K = any, V = any> {
|
|
|
148
226
|
* }
|
|
149
227
|
*
|
|
150
228
|
* // Test case 1: Stable income and good credit score
|
|
151
|
-
* console.log(determineLoanApproval(loanDecisionTree.root, { stableIncome: true, goodCredit: true })); // 'Approved'
|
|
229
|
+
* console.log(determineLoanApproval(loanDecisionTree.root, { stableIncome: true, goodCredit: true })); // 'Approved';
|
|
152
230
|
*
|
|
153
231
|
* // Test case 2: Stable income but poor credit score
|
|
154
|
-
* console.log(determineLoanApproval(loanDecisionTree.root, { stableIncome: true, goodCredit: false })); // 'Rejected'
|
|
232
|
+
* console.log(determineLoanApproval(loanDecisionTree.root, { stableIncome: true, goodCredit: false })); // 'Rejected';
|
|
155
233
|
*
|
|
156
234
|
* // Test case 3: No stable income
|
|
157
|
-
* console.log(determineLoanApproval(loanDecisionTree.root, { stableIncome: false, goodCredit: true })); // 'Rejected'
|
|
235
|
+
* console.log(determineLoanApproval(loanDecisionTree.root, { stableIncome: false, goodCredit: true })); // 'Rejected';
|
|
158
236
|
*
|
|
159
237
|
* // Test case 4: No stable income and poor credit score
|
|
160
|
-
* console.log(determineLoanApproval(loanDecisionTree.root, { stableIncome: false, goodCredit: false })); // 'Rejected'
|
|
238
|
+
* console.log(determineLoanApproval(loanDecisionTree.root, { stableIncome: false, goodCredit: false })); // 'Rejected';
|
|
161
239
|
* @example
|
|
162
240
|
* // evaluate the arithmetic expression represented by the binary tree
|
|
163
|
-
*
|
|
241
|
+
* const expressionTree = new BinaryTree<number | string>(['+', 3, '*', null, null, 5, '-', null, null, 2, 8]);
|
|
164
242
|
*
|
|
165
243
|
* function evaluate(node?: BinaryTreeNode<number | string> | null): number {
|
|
166
244
|
* if (!node) return 0;
|
|
@@ -185,7 +263,7 @@ export declare class BinaryTreeNode<K = any, V = any> {
|
|
|
185
263
|
* }
|
|
186
264
|
* }
|
|
187
265
|
*
|
|
188
|
-
* console.log(evaluate(expressionTree.root)); // -27
|
|
266
|
+
* console.log(evaluate(expressionTree.root)); // -27;
|
|
189
267
|
*/
|
|
190
268
|
export declare class BinaryTree<K = any, V = any, R = any> extends IterableEntryBase<K, V | undefined> implements IBinaryTree<K, V, R> {
|
|
191
269
|
iterationType: IterationType;
|
|
@@ -360,6 +438,15 @@ export declare class BinaryTree<K = any, V = any, R = any> extends IterableEntry
|
|
|
360
438
|
* @returns True if the addition was successful, false otherwise.
|
|
361
439
|
*/
|
|
362
440
|
add(keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined, value?: V): boolean;
|
|
441
|
+
/**
|
|
442
|
+
* Adds or updates a new node to the tree.
|
|
443
|
+
* @remarks Time O(log N), For BST, Red-Black Tree, and AVL Tree subclasses, the worst-case time is O(log N). This implementation adds the node at the first available position in a level-order (BFS) traversal. This is NOT a Binary Search Tree insertion. Time O(N), where N is the number of nodes. It must traverse level-by-level to find an empty slot. Space O(N) in the worst case for the BFS queue (e.g., a full last level).
|
|
444
|
+
*
|
|
445
|
+
* @param keyNodeOrEntry - The key, node, or entry to add or update.
|
|
446
|
+
* @param [value] - The value, if providing just a key.
|
|
447
|
+
* @returns True if the addition was successful, false otherwise.
|
|
448
|
+
*/
|
|
449
|
+
set(keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined, value?: V): boolean;
|
|
363
450
|
/**
|
|
364
451
|
* Adds multiple items to the tree.
|
|
365
452
|
* @remarks Time O(N * M), where N is the number of items to add and M is the size of the tree at insertion (due to O(M) `add` operation). Space O(M) (from `add`) + O(N) (for the `inserted` array).
|
|
@@ -369,6 +456,15 @@ export declare class BinaryTree<K = any, V = any, R = any> extends IterableEntry
|
|
|
369
456
|
* @returns An array of booleans indicating the success of each individual `add` operation.
|
|
370
457
|
*/
|
|
371
458
|
addMany(keysNodesEntriesOrRaws: Iterable<K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | R>, values?: Iterable<V | undefined>): boolean[];
|
|
459
|
+
/**
|
|
460
|
+
* Adds or updates multiple items to the tree.
|
|
461
|
+
* @remarks Time O(N * M), where N is the number of items to add and M is the size of the tree at insertion (due to O(M) `add` operation). Space O(M) (from `add`) + O(N) (for the `inserted` array).
|
|
462
|
+
*
|
|
463
|
+
* @param keysNodesEntriesOrRaws - An iterable of items to add or update.
|
|
464
|
+
* @param [values] - An optional parallel iterable of values.
|
|
465
|
+
* @returns An array of booleans indicating the success of each individual `add` operation.
|
|
466
|
+
*/
|
|
467
|
+
setMany(keysNodesEntriesOrRaws: Iterable<K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | R>, values?: Iterable<V | undefined>): boolean[];
|
|
372
468
|
/**
|
|
373
469
|
* Merges another tree into this one by adding all its nodes.
|
|
374
470
|
* @remarks Time O(N * M), same as `addMany`, where N is the size of `anotherTree` and M is the size of this tree. Space O(M) (from `add`).
|
|
@@ -126,8 +126,57 @@ export declare class BSTNode<K = any, V = any> {
|
|
|
126
126
|
* 7. No Auto-Balancing: Standard BSTs don't automatically balance themselves.
|
|
127
127
|
*
|
|
128
128
|
* @example
|
|
129
|
+
* // basic BST creation and add operation
|
|
130
|
+
* // Create a simple BST with numeric keys
|
|
131
|
+
* const bst = new BST<number>([11, 3, 15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5]);
|
|
132
|
+
*
|
|
133
|
+
* bst.print();
|
|
134
|
+
* // _______8__________
|
|
135
|
+
* // / \
|
|
136
|
+
* // ___4___ ____12_____
|
|
137
|
+
* // / \ / \
|
|
138
|
+
* // _2_ _6_ _10__ _14__
|
|
139
|
+
* // / \ / \ / \ / \
|
|
140
|
+
* // 1 3 5 7 9 11 13 15__
|
|
141
|
+
* // \
|
|
142
|
+
* // 16
|
|
143
|
+
*
|
|
144
|
+
* // Verify size
|
|
145
|
+
* console.log(bst.size); // 16;
|
|
146
|
+
*
|
|
147
|
+
* // Add new elements
|
|
148
|
+
* bst.add(17);
|
|
149
|
+
* bst.add(0);
|
|
150
|
+
* console.log(bst.size); // 18;
|
|
151
|
+
*
|
|
152
|
+
* // Verify keys are searchable
|
|
153
|
+
* console.log(bst.has(11)); // true;
|
|
154
|
+
* console.log(bst.has(100)); // false;
|
|
155
|
+
* @example
|
|
156
|
+
* // BST delete and search after deletion
|
|
157
|
+
* const bst = new BST<number>([11, 3, 15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5]);
|
|
158
|
+
*
|
|
159
|
+
* // Delete a leaf node
|
|
160
|
+
* bst.delete(1);
|
|
161
|
+
* console.log(bst.has(1)); // false;
|
|
162
|
+
*
|
|
163
|
+
* // Delete a node with one child
|
|
164
|
+
* bst.delete(2);
|
|
165
|
+
* console.log(bst.has(2)); // false;
|
|
166
|
+
*
|
|
167
|
+
* // Delete a node with two children
|
|
168
|
+
* bst.delete(3);
|
|
169
|
+
* console.log(bst.has(3)); // false;
|
|
170
|
+
*
|
|
171
|
+
* // Size decreases with each deletion
|
|
172
|
+
* console.log(bst.size); // 13;
|
|
173
|
+
*
|
|
174
|
+
* // Other nodes remain searchable
|
|
175
|
+
* console.log(bst.has(11)); // true;
|
|
176
|
+
* console.log(bst.has(15)); // true;
|
|
177
|
+
* @example
|
|
129
178
|
* // Merge 3 sorted datasets
|
|
130
|
-
*
|
|
179
|
+
* const dataset1 = new BST<number, string>([
|
|
131
180
|
* [1, 'A'],
|
|
132
181
|
* [7, 'G']
|
|
133
182
|
* ]);
|
|
@@ -147,18 +196,58 @@ export declare class BSTNode<K = any, V = any> {
|
|
|
147
196
|
* merged.merge(dataset3);
|
|
148
197
|
*
|
|
149
198
|
* // Verify merged dataset is in sorted order
|
|
150
|
-
* console.log([...merged.values()]); // ['A', 'B', 'C', 'D', 'E', 'F', 'G']
|
|
199
|
+
* console.log([...merged.values()]); // ['A', 'B', 'C', 'D', 'E', 'F', 'G'];
|
|
151
200
|
* @example
|
|
152
|
-
* //
|
|
153
|
-
*
|
|
154
|
-
*
|
|
155
|
-
*
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
201
|
+
* // BST with custom objects for expression evaluation
|
|
202
|
+
* interface Expression {
|
|
203
|
+
* id: number;
|
|
204
|
+
* operator: string;
|
|
205
|
+
* precedence: number;
|
|
206
|
+
* }
|
|
207
|
+
*
|
|
208
|
+
* // BST efficiently stores and retrieves operators by precedence
|
|
209
|
+
* const operatorTree = new BST<number, Expression>(
|
|
210
|
+
* [
|
|
211
|
+
* [1, { id: 1, operator: '+', precedence: 1 }],
|
|
212
|
+
* [2, { id: 2, operator: '*', precedence: 2 }],
|
|
213
|
+
* [3, { id: 3, operator: '/', precedence: 2 }],
|
|
214
|
+
* [4, { id: 4, operator: '-', precedence: 1 }],
|
|
215
|
+
* [5, { id: 5, operator: '^', precedence: 3 }]
|
|
216
|
+
* ],
|
|
217
|
+
* { isMapMode: false }
|
|
218
|
+
* );
|
|
219
|
+
*
|
|
220
|
+
* console.log(operatorTree.size); // 5;
|
|
221
|
+
*
|
|
222
|
+
* // Quick lookup of operators
|
|
223
|
+
* const mult = operatorTree.get(2);
|
|
224
|
+
* console.log(mult?.operator); // '*';
|
|
225
|
+
* console.log(mult?.precedence); // 2;
|
|
226
|
+
*
|
|
227
|
+
* // Check if operator exists
|
|
228
|
+
* console.log(operatorTree.has(5)); // true;
|
|
229
|
+
* console.log(operatorTree.has(99)); // false;
|
|
230
|
+
*
|
|
231
|
+
* // Retrieve operator by precedence level
|
|
232
|
+
* const expNode = operatorTree.getNode(3);
|
|
233
|
+
* console.log(expNode?.key); // 3;
|
|
234
|
+
* console.log(expNode?.value?.precedence); // 2;
|
|
235
|
+
*
|
|
236
|
+
* // Delete operator and verify
|
|
237
|
+
* operatorTree.delete(1);
|
|
238
|
+
* console.log(operatorTree.has(1)); // false;
|
|
239
|
+
* console.log(operatorTree.size); // 4;
|
|
240
|
+
*
|
|
241
|
+
* // Get tree height for optimization analysis
|
|
242
|
+
* const treeHeight = operatorTree.getHeight();
|
|
243
|
+
* console.log(treeHeight); // > 0;
|
|
244
|
+
*
|
|
245
|
+
* // Remaining operators are still accessible
|
|
246
|
+
* const remaining = operatorTree.get(2);
|
|
247
|
+
* console.log(remaining); // defined;
|
|
159
248
|
* @example
|
|
160
249
|
* // Find lowest common ancestor
|
|
161
|
-
*
|
|
250
|
+
* const bst = new BST<number>([20, 10, 30, 5, 15, 25, 35, 3, 7, 12, 18]);
|
|
162
251
|
*
|
|
163
252
|
* // LCA helper function
|
|
164
253
|
* const findLCA = (num1: number, num2: number): number | undefined => {
|
|
@@ -178,9 +267,9 @@ export declare class BSTNode<K = any, V = any> {
|
|
|
178
267
|
* }
|
|
179
268
|
*
|
|
180
269
|
* // Assertions
|
|
181
|
-
* console.log(findLCA(3, 10)); // 7
|
|
182
|
-
* console.log(findLCA(5, 35)); // 15
|
|
183
|
-
* console.log(findLCA(20, 30)); // 25
|
|
270
|
+
* console.log(findLCA(3, 10)); // 7;
|
|
271
|
+
* console.log(findLCA(5, 35)); // 15;
|
|
272
|
+
* console.log(findLCA(20, 30)); // 25;
|
|
184
273
|
*/
|
|
185
274
|
export declare class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implements IBinaryTree<K, V, R> {
|
|
186
275
|
/**
|
|
@@ -355,6 +444,28 @@ export declare class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R>
|
|
|
355
444
|
* @returns An array of booleans indicating the success of each individual `add` operation.
|
|
356
445
|
*/
|
|
357
446
|
addMany(keysNodesEntriesOrRaws: Iterable<R | BTNRep<K, V, BSTNode<K, V>>>, values?: Iterable<V | undefined>, isBalanceAdd?: boolean, iterationType?: IterationType): boolean[];
|
|
447
|
+
/**
|
|
448
|
+
* Returns the first node with a key greater than or equal to the given key.
|
|
449
|
+
* This is equivalent to C++ std::lower_bound on a BST.
|
|
450
|
+
* Supports RECURSIVE and ITERATIVE implementations.
|
|
451
|
+
* Time Complexity: O(log n) on average, O(h) where h is tree height.
|
|
452
|
+
* Space Complexity: O(h) for recursion, O(1) for iteration.
|
|
453
|
+
* @param keyNodeEntryOrPredicate - The key, node, entry, or predicate function to search for.
|
|
454
|
+
* @param iterationType The iteration type (RECURSIVE or ITERATIVE). Defaults to this.iterationType.
|
|
455
|
+
* @returns The first node with key >= given key, or undefined if no such node exists.
|
|
456
|
+
*/
|
|
457
|
+
lowerBound(keyNodeEntryOrPredicate: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BSTNode<K, V>>, iterationType?: IterationType): BSTNode<K, V> | undefined;
|
|
458
|
+
/**
|
|
459
|
+
* Returns the first node with a key strictly greater than the given key.
|
|
460
|
+
* This is equivalent to C++ std::upper_bound on a BST.
|
|
461
|
+
* Supports RECURSIVE and ITERATIVE implementations.
|
|
462
|
+
* Time Complexity: O(log n) on average, O(h) where h is tree height.
|
|
463
|
+
* Space Complexity: O(h) for recursion, O(1) for iteration.
|
|
464
|
+
* @param keyNodeEntryOrPredicate - The key, node, entry, or predicate function to search for.
|
|
465
|
+
* @param iterationType The iteration type (RECURSIVE or ITERATIVE). Defaults to this.iterationType.
|
|
466
|
+
* @returns The first node with key > given key, or undefined if no such node exists.
|
|
467
|
+
*/
|
|
468
|
+
upperBound(keyNodeEntryOrPredicate: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BSTNode<K, V>>, iterationType?: IterationType): BSTNode<K, V> | undefined;
|
|
358
469
|
/**
|
|
359
470
|
* Traverses the tree and returns nodes that are lesser or greater than a target node.
|
|
360
471
|
* @remarks Time O(N), as it performs a full traversal. Space O(log N) or O(N).
|
|
@@ -405,6 +516,38 @@ export declare class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R>
|
|
|
405
516
|
* @returns True if a node was deleted, false otherwise.
|
|
406
517
|
*/
|
|
407
518
|
deleteWhere(predicate: (key: K, value: V | undefined, index: number, tree: this) => boolean): boolean;
|
|
519
|
+
/**
|
|
520
|
+
* (Protected) Core bound search implementation supporting all parameter types.
|
|
521
|
+
* Unified logic for both lowerBound and upperBound.
|
|
522
|
+
* Resolves various input types (Key, Node, Entry, Predicate) using parent class utilities.
|
|
523
|
+
* @param keyNodeEntryOrPredicate - The key, node, entry, or predicate function to search for.
|
|
524
|
+
* @param isLower - True for lowerBound (>=), false for upperBound (>).
|
|
525
|
+
* @param iterationType - The iteration type (RECURSIVE or ITERATIVE).
|
|
526
|
+
* @returns The first matching node, or undefined if no such node exists.
|
|
527
|
+
*/
|
|
528
|
+
protected _bound(keyNodeEntryOrPredicate: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BSTNode<K, V>>, isLower: boolean, iterationType: IterationType): BSTNode<K, V> | undefined;
|
|
529
|
+
/**
|
|
530
|
+
* (Protected) Binary search for bound by key with pruning optimization.
|
|
531
|
+
* Performs standard BST binary search, choosing left or right subtree based on comparator result.
|
|
532
|
+
* For lowerBound: finds first node where key >= target.
|
|
533
|
+
* For upperBound: finds first node where key > target.
|
|
534
|
+
* @param key - The target key to search for.
|
|
535
|
+
* @param isLower - True for lowerBound (>=), false for upperBound (>).
|
|
536
|
+
* @param iterationType - The iteration type (RECURSIVE or ITERATIVE).
|
|
537
|
+
* @returns The first node matching the bound condition, or undefined if none exists.
|
|
538
|
+
*/
|
|
539
|
+
protected _boundByKey(key: K, isLower: boolean, iterationType: IterationType): BSTNode<K, V> | undefined;
|
|
540
|
+
/**
|
|
541
|
+
* (Protected) In-order traversal search by predicate.
|
|
542
|
+
* Falls back to linear in-order traversal when predicate-based search is required.
|
|
543
|
+
* Returns the first node that satisfies the predicate function.
|
|
544
|
+
* Note: Predicate-based search cannot leverage BST's binary search optimization.
|
|
545
|
+
* Time Complexity: O(n) since it may visit every node.
|
|
546
|
+
* @param predicate - The predicate function to test nodes.
|
|
547
|
+
* @param iterationType - The iteration type (RECURSIVE or ITERATIVE).
|
|
548
|
+
* @returns The first node satisfying predicate, or undefined if none found.
|
|
549
|
+
*/
|
|
550
|
+
protected _boundByPredicate(predicate: NodePredicate<BSTNode<K, V>>, iterationType: IterationType): BSTNode<K, V> | undefined;
|
|
408
551
|
/**
|
|
409
552
|
* (Protected) Creates a new, empty instance of the same BST constructor.
|
|
410
553
|
* @remarks Time O(1)
|
|
@@ -112,48 +112,97 @@ export declare class RedBlackTreeNode<K = any, V = any> {
|
|
|
112
112
|
* 2. It is BST itself. Compared with Heap which is not completely ordered, RedBlackTree is completely ordered.
|
|
113
113
|
*
|
|
114
114
|
* @example
|
|
115
|
-
* //
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
*
|
|
115
|
+
* // basic Red-Black Tree with simple number keys
|
|
116
|
+
* // Create a simple Red-Black Tree with numeric keys
|
|
117
|
+
* const tree = new RedBlackTree([5, 2, 8, 1, 9]);
|
|
118
|
+
*
|
|
119
|
+
* tree.print();
|
|
120
|
+
* // _2___
|
|
121
|
+
* // / \
|
|
122
|
+
* // 1 _8_
|
|
123
|
+
* // / \
|
|
124
|
+
* // 5 9
|
|
125
|
+
*
|
|
126
|
+
* // Verify the tree maintains sorted order
|
|
127
|
+
* console.log([...tree.keys()]); // [1, 2, 5, 8, 9];
|
|
128
|
+
*
|
|
129
|
+
* // Check size
|
|
130
|
+
* console.log(tree.size); // 5;
|
|
131
|
+
* @example
|
|
132
|
+
* // Red-Black Tree with key-value pairs for lookups
|
|
133
|
+
* interface Employee {
|
|
134
|
+
* id: number;
|
|
135
|
+
* name: string;
|
|
121
136
|
* }
|
|
122
137
|
*
|
|
123
|
-
* //
|
|
124
|
-
* const
|
|
125
|
-
* {
|
|
126
|
-
* {
|
|
127
|
-
* {
|
|
128
|
-
*
|
|
129
|
-
*
|
|
130
|
-
*
|
|
138
|
+
* // Create tree with employee data
|
|
139
|
+
* const employees = new RedBlackTree<number, Employee>([
|
|
140
|
+
* [1, { id: 1, name: 'Alice' }],
|
|
141
|
+
* [3, { id: 3, name: 'Charlie' }],
|
|
142
|
+
* [2, { id: 2, name: 'Bob' }]
|
|
143
|
+
* ]);
|
|
144
|
+
*
|
|
145
|
+
* // Retrieve employee by ID
|
|
146
|
+
* const alice = employees.get(1);
|
|
147
|
+
* console.log(alice?.name); // 'Alice';
|
|
148
|
+
*
|
|
149
|
+
* // Verify sorted order by ID
|
|
150
|
+
* console.log([...employees.keys()]); // [1, 2, 3];
|
|
151
|
+
* @example
|
|
152
|
+
* // Red-Black Tree range search for filtering
|
|
153
|
+
* interface Product {
|
|
154
|
+
* name: string;
|
|
155
|
+
* price: number;
|
|
156
|
+
* }
|
|
131
157
|
*
|
|
132
|
-
*
|
|
133
|
-
*
|
|
158
|
+
* const products = new RedBlackTree<number, Product>([
|
|
159
|
+
* [10, { name: 'Item A', price: 10 }],
|
|
160
|
+
* [25, { name: 'Item B', price: 25 }],
|
|
161
|
+
* [40, { name: 'Item C', price: 40 }],
|
|
162
|
+
* [50, { name: 'Item D', price: 50 }]
|
|
163
|
+
* ]);
|
|
134
164
|
*
|
|
135
|
-
* //
|
|
136
|
-
*
|
|
137
|
-
*
|
|
138
|
-
* toEntryFn: stockRecord => [
|
|
139
|
-
* stockRecord.price, // Use stock price as the key
|
|
140
|
-
* {
|
|
141
|
-
* ...stockRecord,
|
|
142
|
-
* lastUpdated: new Date() // Add a timestamp for when the record was indexed
|
|
143
|
-
* }
|
|
144
|
-
* ]
|
|
165
|
+
* // Find products in price range [20, 45]
|
|
166
|
+
* const pricesInRange = products.rangeSearch([20, 45], node => {
|
|
167
|
+
* return products.get(node)?.name;
|
|
145
168
|
* });
|
|
146
169
|
*
|
|
147
|
-
* //
|
|
148
|
-
*
|
|
149
|
-
*
|
|
170
|
+
* console.log(pricesInRange); // ['Item B', 'Item C'];
|
|
171
|
+
* @example
|
|
172
|
+
* // Red-Black Tree as database index for stock market data
|
|
173
|
+
* interface StockPrice {
|
|
174
|
+
* symbol: string;
|
|
175
|
+
* volume: number;
|
|
176
|
+
* timestamp: Date;
|
|
177
|
+
* }
|
|
178
|
+
*
|
|
179
|
+
* // Simulate real-time stock price index
|
|
180
|
+
* const priceIndex = new RedBlackTree<number, StockPrice>([
|
|
181
|
+
* [142.5, { symbol: 'AAPL', volume: 1000000, timestamp: new Date() }],
|
|
182
|
+
* [335.2, { symbol: 'MSFT', volume: 800000, timestamp: new Date() }],
|
|
183
|
+
* [3285.04, { symbol: 'AMZN', volume: 500000, timestamp: new Date() }],
|
|
184
|
+
* [267.98, { symbol: 'META', volume: 750000, timestamp: new Date() }],
|
|
185
|
+
* [234.57, { symbol: 'GOOGL', volume: 900000, timestamp: new Date() }]
|
|
186
|
+
* ]);
|
|
187
|
+
*
|
|
188
|
+
* // Find highest-priced stock
|
|
189
|
+
* const maxPrice = priceIndex.getRightMost();
|
|
190
|
+
* console.log(priceIndex.get(maxPrice)?.symbol); // 'AMZN';
|
|
191
|
+
*
|
|
192
|
+
* // Find stocks in price range [200, 400] for portfolio balancing
|
|
193
|
+
* const stocksInRange = priceIndex.rangeSearch([200, 400], node => {
|
|
194
|
+
* const stock = priceIndex.get(node);
|
|
195
|
+
* return {
|
|
196
|
+
* symbol: stock?.symbol,
|
|
197
|
+
* price: node,
|
|
198
|
+
* volume: stock?.volume
|
|
199
|
+
* };
|
|
200
|
+
* });
|
|
150
201
|
*
|
|
151
|
-
*
|
|
152
|
-
*
|
|
153
|
-
*
|
|
154
|
-
*
|
|
155
|
-
* );
|
|
156
|
-
* console.log(stocksInRange); // ['GOOGL', 'META', 'MSFT']
|
|
202
|
+
* console.log(stocksInRange.length); // 3;
|
|
203
|
+
* console.log(stocksInRange.some((s: any) => s.symbol === 'GOOGL')); // true;
|
|
204
|
+
* console.log(stocksInRange.some((s: any) => s.symbol === 'META')); // true;
|
|
205
|
+
* console.log(stocksInRange.some((s: any) => s.symbol === 'MSFT')); // true;
|
|
157
206
|
*/
|
|
158
207
|
export declare class RedBlackTree<K = any, V = any, R = any> extends BST<K, V, R> implements IBinaryTree<K, V, R> {
|
|
159
208
|
constructor(keysNodesEntriesOrRaws?: Iterable<K | RedBlackTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | R>, options?: RedBlackTreeOptions<K, V, R>);
|
|
@@ -116,7 +116,7 @@ export declare class TreeMultiMapNode<K = any, V = any> {
|
|
|
116
116
|
*
|
|
117
117
|
* @example
|
|
118
118
|
* // players ranked by score with their equipment
|
|
119
|
-
*
|
|
119
|
+
* type Equipment = {
|
|
120
120
|
* name: string; // Equipment name
|
|
121
121
|
* quality: 'legendary' | 'epic' | 'rare' | 'common';
|
|
122
122
|
* level: number;
|
|
@@ -277,7 +277,7 @@ export declare class TreeMultiMapNode<K = any, V = any> {
|
|
|
277
277
|
* // },
|
|
278
278
|
* // { name: 'Level 3 Backpack', quality: 'epic', level: 80 }
|
|
279
279
|
* // ]
|
|
280
|
-
* // ]
|
|
280
|
+
* // ];
|
|
281
281
|
*/
|
|
282
282
|
export declare class TreeMultiMap<K = any, V = any, R = any> extends RedBlackTree<K, V[], R> implements IBinaryTree<K, V[], R> {
|
|
283
283
|
/**
|