stack-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.
Files changed (40) hide show
  1. package/README.md +66 -46
  2. package/dist/cjs/index.cjs.map +1 -1
  3. package/dist/cjs-legacy/index.cjs.map +1 -1
  4. package/dist/esm/index.mjs.map +1 -1
  5. package/dist/esm-legacy/index.mjs.map +1 -1
  6. package/dist/types/data-structures/binary-tree/avl-tree.d.ts +96 -2
  7. package/dist/types/data-structures/binary-tree/binary-tree.d.ts +103 -7
  8. package/dist/types/data-structures/binary-tree/bst.d.ts +156 -13
  9. package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +84 -35
  10. package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +2 -2
  11. package/dist/types/data-structures/graph/directed-graph.d.ts +126 -1
  12. package/dist/types/data-structures/graph/undirected-graph.d.ts +160 -1
  13. package/dist/types/data-structures/hash/hash-map.d.ts +110 -27
  14. package/dist/types/data-structures/heap/heap.d.ts +107 -58
  15. package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +72 -404
  16. package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +121 -5
  17. package/dist/types/data-structures/queue/deque.d.ts +95 -67
  18. package/dist/types/data-structures/queue/queue.d.ts +90 -34
  19. package/dist/types/data-structures/stack/stack.d.ts +58 -40
  20. package/dist/types/data-structures/trie/trie.d.ts +109 -47
  21. package/dist/types/interfaces/binary-tree.d.ts +1 -0
  22. package/dist/umd/stack-typed.js.map +1 -1
  23. package/dist/umd/stack-typed.min.js.map +1 -1
  24. package/package.json +2 -2
  25. package/src/data-structures/binary-tree/avl-tree.ts +96 -2
  26. package/src/data-structures/binary-tree/binary-tree.ts +117 -7
  27. package/src/data-structures/binary-tree/bst.ts +322 -13
  28. package/src/data-structures/binary-tree/red-black-tree.ts +84 -35
  29. package/src/data-structures/binary-tree/tree-multi-map.ts +2 -2
  30. package/src/data-structures/graph/directed-graph.ts +126 -1
  31. package/src/data-structures/graph/undirected-graph.ts +160 -1
  32. package/src/data-structures/hash/hash-map.ts +110 -27
  33. package/src/data-structures/heap/heap.ts +107 -58
  34. package/src/data-structures/linked-list/doubly-linked-list.ts +72 -404
  35. package/src/data-structures/linked-list/singly-linked-list.ts +121 -5
  36. package/src/data-structures/queue/deque.ts +95 -67
  37. package/src/data-structures/queue/queue.ts +90 -34
  38. package/src/data-structures/stack/stack.ts +58 -40
  39. package/src/data-structures/trie/trie.ts +109 -47
  40. package/src/interfaces/binary-tree.ts +2 -0
@@ -201,8 +201,57 @@ export class BSTNode<K = any, V = any> {
201
201
  * 7. No Auto-Balancing: Standard BSTs don't automatically balance themselves.
202
202
  *
203
203
  * @example
204
+ * // basic BST creation and add operation
205
+ * // Create a simple BST with numeric keys
206
+ * const bst = new BST<number>([11, 3, 15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5]);
207
+ *
208
+ * bst.print();
209
+ * // _______8__________
210
+ * // / \
211
+ * // ___4___ ____12_____
212
+ * // / \ / \
213
+ * // _2_ _6_ _10__ _14__
214
+ * // / \ / \ / \ / \
215
+ * // 1 3 5 7 9 11 13 15__
216
+ * // \
217
+ * // 16
218
+ *
219
+ * // Verify size
220
+ * console.log(bst.size); // 16;
221
+ *
222
+ * // Add new elements
223
+ * bst.add(17);
224
+ * bst.add(0);
225
+ * console.log(bst.size); // 18;
226
+ *
227
+ * // Verify keys are searchable
228
+ * console.log(bst.has(11)); // true;
229
+ * console.log(bst.has(100)); // false;
230
+ * @example
231
+ * // BST delete and search after deletion
232
+ * const bst = new BST<number>([11, 3, 15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5]);
233
+ *
234
+ * // Delete a leaf node
235
+ * bst.delete(1);
236
+ * console.log(bst.has(1)); // false;
237
+ *
238
+ * // Delete a node with one child
239
+ * bst.delete(2);
240
+ * console.log(bst.has(2)); // false;
241
+ *
242
+ * // Delete a node with two children
243
+ * bst.delete(3);
244
+ * console.log(bst.has(3)); // false;
245
+ *
246
+ * // Size decreases with each deletion
247
+ * console.log(bst.size); // 13;
248
+ *
249
+ * // Other nodes remain searchable
250
+ * console.log(bst.has(11)); // true;
251
+ * console.log(bst.has(15)); // true;
252
+ * @example
204
253
  * // Merge 3 sorted datasets
205
- * const dataset1 = new BST<number, string>([
254
+ * const dataset1 = new BST<number, string>([
206
255
  * [1, 'A'],
207
256
  * [7, 'G']
208
257
  * ]);
@@ -222,18 +271,58 @@ export class BSTNode<K = any, V = any> {
222
271
  * merged.merge(dataset3);
223
272
  *
224
273
  * // Verify merged dataset is in sorted order
225
- * console.log([...merged.values()]); // ['A', 'B', 'C', 'D', 'E', 'F', 'G']
274
+ * console.log([...merged.values()]); // ['A', 'B', 'C', 'D', 'E', 'F', 'G'];
226
275
  * @example
227
- * // Find elements in a range
228
- * const bst = new BST<number>([10, 5, 15, 3, 7, 12, 18]);
229
- * console.log(bst.search(new Range(5, 10))); // [5, 7, 10]
230
- * console.log(bst.rangeSearch([4, 12], node => node.key.toString())); // ['5', '7', '10', '12']
231
- * console.log(bst.search(new Range(4, 12, true, false))); // [5, 7, 10]
232
- * console.log(bst.rangeSearch([15, 20])); // [15, 18]
233
- * console.log(bst.search(new Range(15, 20, false))); // [18]
276
+ * // BST with custom objects for expression evaluation
277
+ * interface Expression {
278
+ * id: number;
279
+ * operator: string;
280
+ * precedence: number;
281
+ * }
282
+ *
283
+ * // BST efficiently stores and retrieves operators by precedence
284
+ * const operatorTree = new BST<number, Expression>(
285
+ * [
286
+ * [1, { id: 1, operator: '+', precedence: 1 }],
287
+ * [2, { id: 2, operator: '*', precedence: 2 }],
288
+ * [3, { id: 3, operator: '/', precedence: 2 }],
289
+ * [4, { id: 4, operator: '-', precedence: 1 }],
290
+ * [5, { id: 5, operator: '^', precedence: 3 }]
291
+ * ],
292
+ * { isMapMode: false }
293
+ * );
294
+ *
295
+ * console.log(operatorTree.size); // 5;
296
+ *
297
+ * // Quick lookup of operators
298
+ * const mult = operatorTree.get(2);
299
+ * console.log(mult?.operator); // '*';
300
+ * console.log(mult?.precedence); // 2;
301
+ *
302
+ * // Check if operator exists
303
+ * console.log(operatorTree.has(5)); // true;
304
+ * console.log(operatorTree.has(99)); // false;
305
+ *
306
+ * // Retrieve operator by precedence level
307
+ * const expNode = operatorTree.getNode(3);
308
+ * console.log(expNode?.key); // 3;
309
+ * console.log(expNode?.value?.precedence); // 2;
310
+ *
311
+ * // Delete operator and verify
312
+ * operatorTree.delete(1);
313
+ * console.log(operatorTree.has(1)); // false;
314
+ * console.log(operatorTree.size); // 4;
315
+ *
316
+ * // Get tree height for optimization analysis
317
+ * const treeHeight = operatorTree.getHeight();
318
+ * console.log(treeHeight); // > 0;
319
+ *
320
+ * // Remaining operators are still accessible
321
+ * const remaining = operatorTree.get(2);
322
+ * console.log(remaining); // defined;
234
323
  * @example
235
324
  * // Find lowest common ancestor
236
- * const bst = new BST<number>([20, 10, 30, 5, 15, 25, 35, 3, 7, 12, 18]);
325
+ * const bst = new BST<number>([20, 10, 30, 5, 15, 25, 35, 3, 7, 12, 18]);
237
326
  *
238
327
  * // LCA helper function
239
328
  * const findLCA = (num1: number, num2: number): number | undefined => {
@@ -253,9 +342,9 @@ export class BSTNode<K = any, V = any> {
253
342
  * }
254
343
  *
255
344
  * // Assertions
256
- * console.log(findLCA(3, 10)); // 7
257
- * console.log(findLCA(5, 35)); // 15
258
- * console.log(findLCA(20, 30)); // 25
345
+ * console.log(findLCA(3, 10)); // 7;
346
+ * console.log(findLCA(5, 35)); // 15;
347
+ * console.log(findLCA(20, 30)); // 25;
259
348
  */
260
349
  export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implements IBinaryTree<K, V, R> {
261
350
  /**
@@ -756,6 +845,52 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
756
845
  return inserted;
757
846
  }
758
847
 
848
+ /**
849
+ * Returns the first node with a key greater than or equal to the given key.
850
+ * This is equivalent to C++ std::lower_bound on a BST.
851
+ * Supports RECURSIVE and ITERATIVE implementations.
852
+ * Time Complexity: O(log n) on average, O(h) where h is tree height.
853
+ * Space Complexity: O(h) for recursion, O(1) for iteration.
854
+ * @param keyNodeEntryOrPredicate - The key, node, entry, or predicate function to search for.
855
+ * @param iterationType The iteration type (RECURSIVE or ITERATIVE). Defaults to this.iterationType.
856
+ * @returns The first node with key >= given key, or undefined if no such node exists.
857
+ */
858
+ lowerBound(
859
+ keyNodeEntryOrPredicate:
860
+ | K
861
+ | BSTNode<K, V>
862
+ | [K | null | undefined, V | undefined]
863
+ | null
864
+ | undefined
865
+ | NodePredicate<BSTNode<K, V>>,
866
+ iterationType: IterationType = this.iterationType
867
+ ): BSTNode<K, V> | undefined {
868
+ return this._bound(keyNodeEntryOrPredicate, true, iterationType);
869
+ }
870
+
871
+ /**
872
+ * Returns the first node with a key strictly greater than the given key.
873
+ * This is equivalent to C++ std::upper_bound on a BST.
874
+ * Supports RECURSIVE and ITERATIVE implementations.
875
+ * Time Complexity: O(log n) on average, O(h) where h is tree height.
876
+ * Space Complexity: O(h) for recursion, O(1) for iteration.
877
+ * @param keyNodeEntryOrPredicate - The key, node, entry, or predicate function to search for.
878
+ * @param iterationType The iteration type (RECURSIVE or ITERATIVE). Defaults to this.iterationType.
879
+ * @returns The first node with key > given key, or undefined if no such node exists.
880
+ */
881
+ upperBound(
882
+ keyNodeEntryOrPredicate:
883
+ | K
884
+ | BSTNode<K, V>
885
+ | [K | null | undefined, V | undefined]
886
+ | null
887
+ | undefined
888
+ | NodePredicate<BSTNode<K, V>>,
889
+ iterationType: IterationType = this.iterationType
890
+ ): BSTNode<K, V> | undefined {
891
+ return this._bound(keyNodeEntryOrPredicate, false, iterationType);
892
+ }
893
+
759
894
  /**
760
895
  * Traverses the tree and returns nodes that are lesser or greater than a target node.
761
896
  * @remarks Time O(N), as it performs a full traversal. Space O(log N) or O(N).
@@ -945,6 +1080,180 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
945
1080
  return false;
946
1081
  }
947
1082
 
1083
+ /**
1084
+ * (Protected) Core bound search implementation supporting all parameter types.
1085
+ * Unified logic for both lowerBound and upperBound.
1086
+ * Resolves various input types (Key, Node, Entry, Predicate) using parent class utilities.
1087
+ * @param keyNodeEntryOrPredicate - The key, node, entry, or predicate function to search for.
1088
+ * @param isLower - True for lowerBound (>=), false for upperBound (>).
1089
+ * @param iterationType - The iteration type (RECURSIVE or ITERATIVE).
1090
+ * @returns The first matching node, or undefined if no such node exists.
1091
+ */
1092
+ protected _bound(
1093
+ keyNodeEntryOrPredicate:
1094
+ | K
1095
+ | BSTNode<K, V>
1096
+ | [K | null | undefined, V | undefined]
1097
+ | null
1098
+ | undefined
1099
+ | NodePredicate<BSTNode<K, V>>,
1100
+ isLower: boolean,
1101
+ iterationType: IterationType
1102
+ ): BSTNode<K, V> | undefined {
1103
+ if (keyNodeEntryOrPredicate === null || keyNodeEntryOrPredicate === undefined) {
1104
+ return undefined;
1105
+ }
1106
+
1107
+ // Check if input is a predicate function first
1108
+ if (this._isPredicate(keyNodeEntryOrPredicate)) {
1109
+ return this._boundByPredicate(keyNodeEntryOrPredicate, iterationType);
1110
+ }
1111
+
1112
+ // Resolve input to a comparable key
1113
+ let targetKey: K | undefined;
1114
+
1115
+ if (this.isNode(keyNodeEntryOrPredicate)) {
1116
+ // Input is a BSTNode - extract its key
1117
+ targetKey = keyNodeEntryOrPredicate.key;
1118
+ } else if (this.isEntry(keyNodeEntryOrPredicate)) {
1119
+ // Input is a [key, value] entry - extract the key
1120
+ const key = keyNodeEntryOrPredicate[0];
1121
+ if (key === null || key === undefined) {
1122
+ return undefined;
1123
+ }
1124
+ targetKey = key;
1125
+ } else {
1126
+ // Input is a raw key
1127
+ targetKey = keyNodeEntryOrPredicate;
1128
+ }
1129
+
1130
+ // Execute key-based search with binary search optimization
1131
+ if (targetKey !== undefined) {
1132
+ return this._boundByKey(targetKey, isLower, iterationType);
1133
+ }
1134
+
1135
+ return undefined;
1136
+ }
1137
+
1138
+ /**
1139
+ * (Protected) Binary search for bound by key with pruning optimization.
1140
+ * Performs standard BST binary search, choosing left or right subtree based on comparator result.
1141
+ * For lowerBound: finds first node where key >= target.
1142
+ * For upperBound: finds first node where key > target.
1143
+ * @param key - The target key to search for.
1144
+ * @param isLower - True for lowerBound (>=), false for upperBound (>).
1145
+ * @param iterationType - The iteration type (RECURSIVE or ITERATIVE).
1146
+ * @returns The first node matching the bound condition, or undefined if none exists.
1147
+ */
1148
+ protected _boundByKey(key: K, isLower: boolean, iterationType: IterationType): BSTNode<K, V> | undefined {
1149
+ if (iterationType === 'RECURSIVE') {
1150
+ // Recursive binary search implementation
1151
+ const dfs = (cur: BSTNode<K, V> | null | undefined): BSTNode<K, V> | undefined => {
1152
+ if (!this.isRealNode(cur)) return undefined;
1153
+
1154
+ const cmp = this.comparator(cur.key!, key);
1155
+ const condition = isLower ? cmp >= 0 : cmp > 0;
1156
+
1157
+ if (condition) {
1158
+ // Current node satisfies the bound condition.
1159
+ // Try to find a closer (smaller key) candidate in the left subtree.
1160
+ const leftResult = dfs(cur.left);
1161
+ return leftResult ?? cur;
1162
+ } else {
1163
+ // Current node does not satisfy the condition.
1164
+ // Move right to find larger keys.
1165
+ return dfs(cur.right);
1166
+ }
1167
+ };
1168
+
1169
+ return dfs(this.root);
1170
+ } else {
1171
+ // Iterative binary search implementation
1172
+ let current: BSTNode<K, V> | undefined = this.root;
1173
+ let result: BSTNode<K, V> | undefined = undefined;
1174
+
1175
+ while (this.isRealNode(current)) {
1176
+ const cmp = this.comparator(current.key!, key);
1177
+ const condition = isLower ? cmp >= 0 : cmp > 0;
1178
+
1179
+ if (condition) {
1180
+ // Current node is a candidate. Save it and try left subtree for a closer match.
1181
+ result = current;
1182
+ current = current.left ?? undefined;
1183
+ } else {
1184
+ // Move right to find larger keys.
1185
+ current = current.right ?? undefined;
1186
+ }
1187
+ }
1188
+
1189
+ return result;
1190
+ }
1191
+ }
1192
+
1193
+ /**
1194
+ * (Protected) In-order traversal search by predicate.
1195
+ * Falls back to linear in-order traversal when predicate-based search is required.
1196
+ * Returns the first node that satisfies the predicate function.
1197
+ * Note: Predicate-based search cannot leverage BST's binary search optimization.
1198
+ * Time Complexity: O(n) since it may visit every node.
1199
+ * @param predicate - The predicate function to test nodes.
1200
+ * @param iterationType - The iteration type (RECURSIVE or ITERATIVE).
1201
+ * @returns The first node satisfying predicate, or undefined if none found.
1202
+ */
1203
+ protected _boundByPredicate(
1204
+ predicate: NodePredicate<BSTNode<K, V>>,
1205
+ iterationType: IterationType
1206
+ ): BSTNode<K, V> | undefined {
1207
+ if (iterationType === 'RECURSIVE') {
1208
+ // Recursive in-order traversal
1209
+ let result: BSTNode<K, V> | undefined = undefined;
1210
+
1211
+ const dfs = (cur: BSTNode<K, V> | null | undefined): void => {
1212
+ if (result || !this.isRealNode(cur)) return;
1213
+
1214
+ // In-order: process left subtree first
1215
+ if (this.isRealNode(cur.left)) dfs(cur.left);
1216
+
1217
+ // Check current node
1218
+ if (!result && predicate(cur)) {
1219
+ result = cur;
1220
+ }
1221
+
1222
+ // Process right subtree
1223
+ if (!result && this.isRealNode(cur.right)) dfs(cur.right);
1224
+ };
1225
+
1226
+ dfs(this.root);
1227
+ return result;
1228
+ } else {
1229
+ // Iterative in-order traversal using explicit stack
1230
+ const stack: (BSTNode<K, V> | null | undefined)[] = [];
1231
+ let current: BSTNode<K, V> | null | undefined = this.root;
1232
+
1233
+ while (stack.length > 0 || this.isRealNode(current)) {
1234
+ if (this.isRealNode(current)) {
1235
+ // Go to the leftmost node
1236
+ stack.push(current);
1237
+ current = current.left;
1238
+ } else {
1239
+ // Pop from stack and process
1240
+ const node = stack.pop();
1241
+ if (!this.isRealNode(node)) break;
1242
+
1243
+ // Check if current node satisfies predicate
1244
+ if (predicate(node)) {
1245
+ return node;
1246
+ }
1247
+
1248
+ // Visit right subtree
1249
+ current = node.right;
1250
+ }
1251
+ }
1252
+
1253
+ return undefined;
1254
+ }
1255
+ }
1256
+
948
1257
  /**
949
1258
  * (Protected) Creates a new, empty instance of the same BST constructor.
950
1259
  * @remarks Time O(1)
@@ -188,48 +188,97 @@ export class RedBlackTreeNode<K = any, V = any> {
188
188
  * 2. It is BST itself. Compared with Heap which is not completely ordered, RedBlackTree is completely ordered.
189
189
  *
190
190
  * @example
191
- * // using Red-Black Tree as a price-based index for stock data
192
- * // Define the structure of individual stock records
193
- * interface StockRecord {
194
- * price: number; // Stock price (key for indexing)
195
- * symbol: string; // Stock ticker symbol
196
- * volume: number; // Trade volume
191
+ * // basic Red-Black Tree with simple number keys
192
+ * // Create a simple Red-Black Tree with numeric keys
193
+ * const tree = new RedBlackTree([5, 2, 8, 1, 9]);
194
+ *
195
+ * tree.print();
196
+ * // _2___
197
+ * // / \
198
+ * // 1 _8_
199
+ * // / \
200
+ * // 5 9
201
+ *
202
+ * // Verify the tree maintains sorted order
203
+ * console.log([...tree.keys()]); // [1, 2, 5, 8, 9];
204
+ *
205
+ * // Check size
206
+ * console.log(tree.size); // 5;
207
+ * @example
208
+ * // Red-Black Tree with key-value pairs for lookups
209
+ * interface Employee {
210
+ * id: number;
211
+ * name: string;
197
212
  * }
198
213
  *
199
- * // Simulate stock market data as it might come from an external feed
200
- * const marketStockData: StockRecord[] = [
201
- * { price: 142.5, symbol: 'AAPL', volume: 1000000 },
202
- * { price: 335.2, symbol: 'MSFT', volume: 800000 },
203
- * { price: 3285.04, symbol: 'AMZN', volume: 500000 },
204
- * { price: 267.98, symbol: 'META', volume: 750000 },
205
- * { price: 234.57, symbol: 'GOOGL', volume: 900000 }
206
- * ];
214
+ * // Create tree with employee data
215
+ * const employees = new RedBlackTree<number, Employee>([
216
+ * [1, { id: 1, name: 'Alice' }],
217
+ * [3, { id: 3, name: 'Charlie' }],
218
+ * [2, { id: 2, name: 'Bob' }]
219
+ * ]);
220
+ *
221
+ * // Retrieve employee by ID
222
+ * const alice = employees.get(1);
223
+ * console.log(alice?.name); // 'Alice';
224
+ *
225
+ * // Verify sorted order by ID
226
+ * console.log([...employees.keys()]); // [1, 2, 3];
227
+ * @example
228
+ * // Red-Black Tree range search for filtering
229
+ * interface Product {
230
+ * name: string;
231
+ * price: number;
232
+ * }
207
233
  *
208
- * // Extend the stock record type to include metadata for database usage
209
- * type StockTableRecord = StockRecord & { lastUpdated: Date };
234
+ * const products = new RedBlackTree<number, Product>([
235
+ * [10, { name: 'Item A', price: 10 }],
236
+ * [25, { name: 'Item B', price: 25 }],
237
+ * [40, { name: 'Item C', price: 40 }],
238
+ * [50, { name: 'Item D', price: 50 }]
239
+ * ]);
210
240
  *
211
- * // Create a Red-Black Tree to index stock records by price
212
- * // Simulates a database index with stock price as the key for quick lookups
213
- * const priceIndex = new RedBlackTree<number, StockTableRecord, StockRecord>(marketStockData, {
214
- * toEntryFn: stockRecord => [
215
- * stockRecord.price, // Use stock price as the key
216
- * {
217
- * ...stockRecord,
218
- * lastUpdated: new Date() // Add a timestamp for when the record was indexed
219
- * }
220
- * ]
241
+ * // Find products in price range [20, 45]
242
+ * const pricesInRange = products.rangeSearch([20, 45], node => {
243
+ * return products.get(node)?.name;
221
244
  * });
222
245
  *
223
- * // Query the stock with the highest price
224
- * const highestPricedStock = priceIndex.getRightMost();
225
- * console.log(priceIndex.get(highestPricedStock)?.symbol); // 'AMZN' // Amazon has the highest price
246
+ * console.log(pricesInRange); // ['Item B', 'Item C'];
247
+ * @example
248
+ * // Red-Black Tree as database index for stock market data
249
+ * interface StockPrice {
250
+ * symbol: string;
251
+ * volume: number;
252
+ * timestamp: Date;
253
+ * }
254
+ *
255
+ * // Simulate real-time stock price index
256
+ * const priceIndex = new RedBlackTree<number, StockPrice>([
257
+ * [142.5, { symbol: 'AAPL', volume: 1000000, timestamp: new Date() }],
258
+ * [335.2, { symbol: 'MSFT', volume: 800000, timestamp: new Date() }],
259
+ * [3285.04, { symbol: 'AMZN', volume: 500000, timestamp: new Date() }],
260
+ * [267.98, { symbol: 'META', volume: 750000, timestamp: new Date() }],
261
+ * [234.57, { symbol: 'GOOGL', volume: 900000, timestamp: new Date() }]
262
+ * ]);
263
+ *
264
+ * // Find highest-priced stock
265
+ * const maxPrice = priceIndex.getRightMost();
266
+ * console.log(priceIndex.get(maxPrice)?.symbol); // 'AMZN';
267
+ *
268
+ * // Find stocks in price range [200, 400] for portfolio balancing
269
+ * const stocksInRange = priceIndex.rangeSearch([200, 400], node => {
270
+ * const stock = priceIndex.get(node);
271
+ * return {
272
+ * symbol: stock?.symbol,
273
+ * price: node,
274
+ * volume: stock?.volume
275
+ * };
276
+ * });
226
277
  *
227
- * // Query stocks within a specific price range (200 to 400)
228
- * const stocksInRange = priceIndex.rangeSearch(
229
- * [200, 400], // Price range
230
- * node => priceIndex.get(node)?.symbol // Extract stock symbols for the result
231
- * );
232
- * console.log(stocksInRange); // ['GOOGL', 'META', 'MSFT']
278
+ * console.log(stocksInRange.length); // 3;
279
+ * console.log(stocksInRange.some((s: any) => s.symbol === 'GOOGL')); // true;
280
+ * console.log(stocksInRange.some((s: any) => s.symbol === 'META')); // true;
281
+ * console.log(stocksInRange.some((s: any) => s.symbol === 'MSFT')); // true;
233
282
  */
234
283
 
235
284
  export class RedBlackTree<K = any, V = any, R = any> extends BST<K, V, R> implements IBinaryTree<K, V, R> {
@@ -186,7 +186,7 @@ export class TreeMultiMapNode<K = any, V = any> {
186
186
  *
187
187
  * @example
188
188
  * // players ranked by score with their equipment
189
- * type Equipment = {
189
+ * type Equipment = {
190
190
  * name: string; // Equipment name
191
191
  * quality: 'legendary' | 'epic' | 'rare' | 'common';
192
192
  * level: number;
@@ -347,7 +347,7 @@ export class TreeMultiMapNode<K = any, V = any> {
347
347
  * // },
348
348
  * // { name: 'Level 3 Backpack', quality: 'epic', level: 80 }
349
349
  * // ]
350
- * // ]
350
+ * // ];
351
351
  */
352
352
  export class TreeMultiMap<K = any, V = any, R = any> extends RedBlackTree<K, V[], R> implements IBinaryTree<K, V[], R> {
353
353
  /**
@@ -35,7 +35,132 @@ export class DirectedEdge<E = any> extends AbstractEdge<E> {
35
35
  * @template VO - Concrete vertex class (extends AbstractVertex<V>).
36
36
  * @template EO - Concrete edge class (extends AbstractEdge<E>).
37
37
  * @remarks Time O(1), Space O(1)
38
- * @example examples will be generated by unit test
38
+ * @example
39
+ * // basic DirectedGraph vertex and edge creation
40
+ * // Create a simple directed graph
41
+ * const graph = new DirectedGraph<string>();
42
+ *
43
+ * // Add vertices
44
+ * graph.addVertex('A');
45
+ * graph.addVertex('B');
46
+ * graph.addVertex('C');
47
+ *
48
+ * // Verify vertices exist
49
+ * console.log(graph.hasVertex('A')); // true;
50
+ * console.log(graph.hasVertex('B')); // true;
51
+ * console.log(graph.hasVertex('C')); // true;
52
+ * console.log(graph.hasVertex('D')); // false;
53
+ *
54
+ * // Check vertex count
55
+ * console.log(graph.size); // 3;
56
+ * @example
57
+ * // DirectedGraph edge operations
58
+ * const graph = new DirectedGraph<string>();
59
+ *
60
+ * // Add vertices
61
+ * graph.addVertex('A');
62
+ * graph.addVertex('B');
63
+ * graph.addVertex('C');
64
+ *
65
+ * // Add directed edges
66
+ * graph.addEdge('A', 'B', 1);
67
+ * graph.addEdge('B', 'C', 2);
68
+ * graph.addEdge('A', 'C', 3);
69
+ *
70
+ * // Verify edges exist
71
+ * console.log(graph.hasEdge('A', 'B')); // true;
72
+ * console.log(graph.hasEdge('B', 'C')); // true;
73
+ * console.log(graph.hasEdge('C', 'B')); // false; // Graph is directed
74
+ *
75
+ * // Get neighbors of A
76
+ * const neighborsA = graph.getNeighbors('A');
77
+ * console.log(neighborsA[0].key); // 'B';
78
+ * console.log(neighborsA[1].key); // 'C';
79
+ * @example
80
+ * // DirectedGraph deleteEdge and vertex operations
81
+ * const graph = new DirectedGraph<string>();
82
+ *
83
+ * // Build a small graph
84
+ * graph.addVertex('X');
85
+ * graph.addVertex('Y');
86
+ * graph.addVertex('Z');
87
+ * graph.addEdge('X', 'Y', 1);
88
+ * graph.addEdge('Y', 'Z', 2);
89
+ *
90
+ * // Delete an edge
91
+ * graph.deleteEdgeSrcToDest('X', 'Y');
92
+ * console.log(graph.hasEdge('X', 'Y')); // false;
93
+ *
94
+ * // Edge in other direction should not exist
95
+ * console.log(graph.hasEdge('Y', 'X')); // false;
96
+ *
97
+ * // Other edges should remain
98
+ * console.log(graph.hasEdge('Y', 'Z')); // true;
99
+ *
100
+ * // Delete a vertex
101
+ * graph.deleteVertex('Y');
102
+ * console.log(graph.hasVertex('Y')); // false;
103
+ * console.log(graph.size); // 2;
104
+ * @example
105
+ * // DirectedGraph topologicalSort for task scheduling
106
+ * const graph = new DirectedGraph<string>();
107
+ *
108
+ * // Build a DAG (Directed Acyclic Graph) for task dependencies
109
+ * graph.addVertex('Design');
110
+ * graph.addVertex('Implement');
111
+ * graph.addVertex('Test');
112
+ * graph.addVertex('Deploy');
113
+ *
114
+ * // Add dependency edges
115
+ * graph.addEdge('Design', 'Implement', 1); // Design must come before Implement
116
+ * graph.addEdge('Implement', 'Test', 1); // Implement must come before Test
117
+ * graph.addEdge('Test', 'Deploy', 1); // Test must come before Deploy
118
+ *
119
+ * // Topological sort gives valid execution order
120
+ * const executionOrder = graph.topologicalSort();
121
+ * console.log(executionOrder); // defined;
122
+ * console.log(executionOrder); // ['Design', 'Implement', 'Test', 'Deploy'];
123
+ *
124
+ * // All vertices should be included
125
+ * console.log(executionOrder?.length); // 4;
126
+ * @example
127
+ * // DirectedGraph dijkstra shortest path for network routing
128
+ * // Build a weighted directed graph representing network nodes and costs
129
+ * const network = new DirectedGraph<string>();
130
+ *
131
+ * // Add network nodes
132
+ * network.addVertex('Router-A');
133
+ * network.addVertex('Router-B');
134
+ * network.addVertex('Router-C');
135
+ * network.addVertex('Router-D');
136
+ * network.addVertex('Router-E');
137
+ *
138
+ * // Add weighted edges (network latency costs)
139
+ * network.addEdge('Router-A', 'Router-B', 5);
140
+ * network.addEdge('Router-A', 'Router-C', 10);
141
+ * network.addEdge('Router-B', 'Router-D', 3);
142
+ * network.addEdge('Router-C', 'Router-D', 2);
143
+ * network.addEdge('Router-D', 'Router-E', 4);
144
+ * network.addEdge('Router-B', 'Router-E', 12);
145
+ *
146
+ * // Find shortest path from Router-A to Router-E
147
+ * const { minDist, minPath } = network.dijkstra('Router-A', 'Router-E', true, true) || {
148
+ * minDist: undefined,
149
+ * minPath: undefined
150
+ * };
151
+ *
152
+ * // Verify shortest path is found
153
+ * console.log(minDist); // defined;
154
+ * console.log(minPath); // defined;
155
+ *
156
+ * // Shortest path should be A -> B -> D -> E with cost 5+3+4=12
157
+ * // Or A -> C -> D -> E with cost 10+2+4=16
158
+ * // So the minimum is 12
159
+ * console.log(minDist); // <= 16;
160
+ *
161
+ * // Verify path is valid (includes start and end)
162
+ * console.log(minPath?.[0].key); // 'Router-A';
163
+ * console.log(minPath?.[minPath.length - 1].key); // 'Router-E';
39
164
  */
40
165
  export class DirectedGraph<
41
166
  V = any,