bst-typed 1.51.7 → 1.51.8

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 (41) hide show
  1. package/dist/data-structures/binary-tree/avl-tree-multi-map.d.ts +3 -12
  2. package/dist/data-structures/binary-tree/avl-tree-multi-map.js +1 -10
  3. package/dist/data-structures/binary-tree/avl-tree.d.ts +3 -3
  4. package/dist/data-structures/binary-tree/avl-tree.js +12 -12
  5. package/dist/data-structures/binary-tree/binary-tree.d.ts +5 -12
  6. package/dist/data-structures/binary-tree/binary-tree.js +22 -32
  7. package/dist/data-structures/binary-tree/bst.d.ts +32 -77
  8. package/dist/data-structures/binary-tree/bst.js +68 -136
  9. package/dist/data-structures/binary-tree/rb-tree.d.ts +3 -13
  10. package/dist/data-structures/binary-tree/rb-tree.js +3 -20
  11. package/dist/data-structures/binary-tree/tree-multi-map.d.ts +3 -4
  12. package/dist/data-structures/heap/heap.d.ts +1 -3
  13. package/dist/interfaces/binary-tree.d.ts +3 -3
  14. package/dist/types/common.d.ts +1 -1
  15. package/dist/types/data-structures/binary-tree/avl-tree-multi-map.d.ts +3 -2
  16. package/dist/types/data-structures/binary-tree/avl-tree.d.ts +3 -2
  17. package/dist/types/data-structures/binary-tree/binary-tree.d.ts +4 -4
  18. package/dist/types/data-structures/binary-tree/bst.d.ts +6 -5
  19. package/dist/types/data-structures/binary-tree/rb-tree.d.ts +4 -3
  20. package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +3 -2
  21. package/dist/types/utils/utils.d.ts +10 -1
  22. package/dist/utils/utils.d.ts +2 -1
  23. package/dist/utils/utils.js +29 -1
  24. package/package.json +2 -2
  25. package/src/data-structures/binary-tree/avl-tree-multi-map.ts +4 -12
  26. package/src/data-structures/binary-tree/avl-tree.ts +15 -14
  27. package/src/data-structures/binary-tree/binary-tree.ts +29 -38
  28. package/src/data-structures/binary-tree/bst.ts +78 -148
  29. package/src/data-structures/binary-tree/rb-tree.ts +8 -22
  30. package/src/data-structures/binary-tree/tree-multi-map.ts +4 -3
  31. package/src/data-structures/heap/heap.ts +1 -1
  32. package/src/interfaces/binary-tree.ts +4 -3
  33. package/src/types/common.ts +1 -1
  34. package/src/types/data-structures/binary-tree/avl-tree-multi-map.ts +3 -2
  35. package/src/types/data-structures/binary-tree/avl-tree.ts +3 -2
  36. package/src/types/data-structures/binary-tree/binary-tree.ts +5 -5
  37. package/src/types/data-structures/binary-tree/bst.ts +6 -5
  38. package/src/types/data-structures/binary-tree/rb-tree.ts +4 -3
  39. package/src/types/data-structures/binary-tree/tree-multi-map.ts +3 -2
  40. package/src/types/utils/utils.ts +14 -1
  41. package/src/utils/utils.ts +20 -1
@@ -5,4 +5,13 @@ export type Thunk = () => ReturnType<ToThunkFn> & {
5
5
  export type TrlFn = (...args: any[]) => any;
6
6
  export type TrlAsyncFn = (...args: any[]) => any;
7
7
  export type SpecifyOptional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
8
- export type Any = string | number | boolean | object | null | undefined | symbol;
8
+ export type Any = string | number | bigint | boolean | symbol | undefined | object;
9
+ export type Comparable = number | string | bigint | boolean | ({
10
+ [key in string]: any;
11
+ } & {
12
+ valueOf(): Comparable;
13
+ }) | ({
14
+ [key in string]: any;
15
+ } & {
16
+ toString(): Comparable;
17
+ }) | (() => Comparable);
@@ -5,7 +5,7 @@
5
5
  * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>
6
6
  * @license MIT License
7
7
  */
8
- import type { Thunk, ToThunkFn, TrlAsyncFn, TrlFn } from '../types';
8
+ import type { Comparable, Thunk, ToThunkFn, TrlAsyncFn, TrlFn } from '../types';
9
9
  export declare const uuidV4: () => string;
10
10
  export declare const arrayRemove: <T>(array: T[], predicate: (item: T, index: number, array: T[]) => boolean) => T[];
11
11
  export declare const THUNK_SYMBOL: unique symbol;
@@ -23,3 +23,4 @@ export declare const throwRangeError: (message?: string) => void;
23
23
  export declare const isWeakKey: (input: unknown) => input is object;
24
24
  export declare const calcMinUnitsRequired: (totalQuantity: number, unitSize: number) => number;
25
25
  export declare const roundFixed: (num: number, digit?: number) => number;
26
+ export declare function isComparable(key: any): key is Comparable;
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.roundFixed = exports.calcMinUnitsRequired = exports.isWeakKey = exports.throwRangeError = exports.rangeCheck = exports.getMSB = exports.trampolineAsync = exports.trampoline = exports.toThunk = exports.isThunk = exports.THUNK_SYMBOL = exports.arrayRemove = exports.uuidV4 = void 0;
12
+ exports.isComparable = exports.roundFixed = exports.calcMinUnitsRequired = exports.isWeakKey = exports.throwRangeError = exports.rangeCheck = exports.getMSB = exports.trampolineAsync = exports.trampoline = exports.toThunk = exports.isThunk = exports.THUNK_SYMBOL = exports.arrayRemove = exports.uuidV4 = void 0;
13
13
  const uuidV4 = function () {
14
14
  return 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'.replace(/[x]/g, function (c) {
15
15
  const r = (Math.random() * 16) | 0, v = c == 'x' ? r : (r & 0x3) | 0x8;
@@ -92,3 +92,31 @@ const roundFixed = (num, digit = 10) => {
92
92
  return Math.round(num * multiplier) / multiplier;
93
93
  };
94
94
  exports.roundFixed = roundFixed;
95
+ function isComparable(key) {
96
+ const keyType = typeof key;
97
+ if (keyType === 'number')
98
+ return isNaN(key);
99
+ if (keyType === 'string')
100
+ return true;
101
+ if (keyType === 'bigint')
102
+ return true;
103
+ if (keyType === 'boolean')
104
+ return true;
105
+ if (keyType === 'symbol')
106
+ return false;
107
+ if (keyType === 'undefined')
108
+ return false;
109
+ if (keyType === 'function')
110
+ return isComparable(key());
111
+ if (keyType === 'object') {
112
+ if (key === null)
113
+ return true;
114
+ if (typeof key.valueOf === 'function')
115
+ return isComparable(key.valueOf());
116
+ if (typeof key.toString === 'function')
117
+ return isComparable(key.toString());
118
+ return false;
119
+ }
120
+ return false;
121
+ }
122
+ exports.isComparable = isComparable;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bst-typed",
3
- "version": "1.51.7",
3
+ "version": "1.51.8",
4
4
  "description": "BST (Binary Search Tree). Javascript & Typescript Data Structure.",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -144,6 +144,6 @@
144
144
  "typescript": "^4.9.5"
145
145
  },
146
146
  "dependencies": {
147
- "data-structure-typed": "^1.51.7"
147
+ "data-structure-typed": "^1.51.8"
148
148
  }
149
149
  }
@@ -12,6 +12,7 @@ import type {
12
12
  BinaryTreeDeleteResult,
13
13
  BSTNKeyOrNode,
14
14
  BTNCallback,
15
+ Comparable,
15
16
  IterationType,
16
17
  KeyOrNodeOrEntry
17
18
  } from '../../types';
@@ -19,7 +20,7 @@ import { IBinaryTree } from '../../interfaces';
19
20
  import { AVLTree, AVLTreeNode } from './avl-tree';
20
21
 
21
22
  export class AVLTreeMultiMapNode<
22
- K = any,
23
+ K extends Comparable,
23
24
  V = any,
24
25
  NODE extends AVLTreeMultiMapNode<K, V, NODE> = AVLTreeMultiMapNodeNested<K, V>
25
26
  > extends AVLTreeNode<K, V, NODE> {
@@ -62,7 +63,7 @@ export class AVLTreeMultiMapNode<
62
63
  * The only distinction between a AVLTreeMultiMap and a AVLTree lies in the ability of the former to store duplicate nodes through the utilization of counters.
63
64
  */
64
65
  export class AVLTreeMultiMap<
65
- K = any,
66
+ K extends Comparable,
66
67
  V = any,
67
68
  NODE extends AVLTreeMultiMapNode<K, V, NODE> = AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNodeNested<K, V>>,
68
69
  TREE extends AVLTreeMultiMap<K, V, NODE, TREE> = AVLTreeMultiMap<K, V, NODE, AVLTreeMultiMapNested<K, V, NODE>>
@@ -118,19 +119,10 @@ export class AVLTreeMultiMap<
118
119
  return new AVLTreeMultiMapNode(key, value, count) as NODE;
119
120
  }
120
121
 
121
- /**
122
- * The function creates a new AVLTreeMultiMap object with the specified options and returns it.
123
- * @param [options] - The `options` parameter is an optional object that contains additional
124
- * configuration options for creating the `AVLTreeMultiMap` object. It can include properties such as
125
- * `iterationType` and `variant`, which are used to specify the type of iteration and the variant of
126
- * the tree, respectively. These properties can be
127
- * @returns a new instance of the `AVLTreeMultiMap` class, with the provided options merged with the
128
- * default options. The returned value is casted as `TREE`.
129
- */
130
122
  override createTree(options?: AVLTreeMultiMapOptions<K>): TREE {
131
123
  return new AVLTreeMultiMap<K, V, NODE, TREE>([], {
132
124
  iterationType: this.iterationType,
133
- variant: this.variant,
125
+ comparator: this.comparator,
134
126
  ...options
135
127
  }) as TREE;
136
128
  }
@@ -13,12 +13,13 @@ import type {
13
13
  BinaryTreeDeleteResult,
14
14
  BSTNKeyOrNode,
15
15
  BTNCallback,
16
+ Comparable,
16
17
  KeyOrNodeOrEntry
17
18
  } from '../../types';
18
19
  import { IBinaryTree } from '../../interfaces';
19
20
 
20
21
  export class AVLTreeNode<
21
- K = any,
22
+ K extends Comparable,
22
23
  V = any,
23
24
  NODE extends AVLTreeNode<K, V, NODE> = AVLTreeNodeNested<K, V>
24
25
  > extends BSTNode<K, V, NODE> {
@@ -65,7 +66,7 @@ export class AVLTreeNode<
65
66
  * 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.
66
67
  */
67
68
  export class AVLTree<
68
- K = any,
69
+ K extends Comparable,
69
70
  V = any,
70
71
  NODE extends AVLTreeNode<K, V, NODE> = AVLTreeNode<K, V, AVLTreeNodeNested<K, V>>,
71
72
  TREE extends AVLTree<K, V, NODE, TREE> = AVLTree<K, V, NODE, AVLTreeNested<K, V, NODE>>
@@ -109,7 +110,7 @@ export class AVLTree<
109
110
  override createTree(options?: AVLTreeOptions<K>): TREE {
110
111
  return new AVLTree<K, V, NODE, TREE>([], {
111
112
  iterationType: this.iterationType,
112
- variant: this.variant,
113
+ comparator: this.comparator,
113
114
  ...options
114
115
  }) as TREE;
115
116
  }
@@ -195,26 +196,26 @@ export class AVLTree<
195
196
  srcNode: BSTNKeyOrNode<K, NODE>,
196
197
  destNode: BSTNKeyOrNode<K, NODE>
197
198
  ): NODE | undefined {
198
- srcNode = this.ensureNode(srcNode);
199
- destNode = this.ensureNode(destNode);
199
+ const srcNodeEnsured = this.ensureNode(srcNode);
200
+ const destNodeEnsured = this.ensureNode(destNode);
200
201
 
201
- if (srcNode && destNode) {
202
- const { key, value, height } = destNode;
202
+ if (srcNodeEnsured && destNodeEnsured) {
203
+ const { key, value, height } = destNodeEnsured;
203
204
  const tempNode = this.createNode(key, value);
204
205
 
205
206
  if (tempNode) {
206
207
  tempNode.height = height;
207
208
 
208
- destNode.key = srcNode.key;
209
- destNode.value = srcNode.value;
210
- destNode.height = srcNode.height;
209
+ destNodeEnsured.key = srcNodeEnsured.key;
210
+ destNodeEnsured.value = srcNodeEnsured.value;
211
+ destNodeEnsured.height = srcNodeEnsured.height;
211
212
 
212
- srcNode.key = tempNode.key;
213
- srcNode.value = tempNode.value;
214
- srcNode.height = tempNode.height;
213
+ srcNodeEnsured.key = tempNode.key;
214
+ srcNodeEnsured.value = tempNode.value;
215
+ srcNodeEnsured.height = tempNode.height;
215
216
  }
216
217
 
217
- return destNode;
218
+ return destNodeEnsured;
218
219
  }
219
220
  return undefined;
220
221
  }
@@ -14,12 +14,14 @@ import type {
14
14
  BinaryTreePrintOptions,
15
15
  BTNCallback,
16
16
  BTNEntry,
17
+ Comparable,
17
18
  DFSOrderPattern,
18
19
  EntryCallback,
20
+ FamilyPosition,
21
+ IterationType,
19
22
  KeyOrNodeOrEntry,
20
23
  NodeDisplayLayout
21
24
  } from '../../types';
22
- import { FamilyPosition, IterationType } from '../../types';
23
25
  import { IBinaryTree } from '../../interfaces';
24
26
  import { trampoline } from '../../utils';
25
27
  import { Queue } from '../queue';
@@ -31,7 +33,7 @@ import { IterableEntryBase } from '../base';
31
33
  * @template NODE - The type of the family relationship in the binary tree.
32
34
  */
33
35
  export class BinaryTreeNode<
34
- K = any,
36
+ K extends Comparable,
35
37
  V = any,
36
38
  NODE extends BinaryTreeNode<K, V, NODE> = BinaryTreeNode<K, V, BinaryTreeNodeNested<K, V>>
37
39
  > {
@@ -129,7 +131,7 @@ export class BinaryTreeNode<
129
131
  */
130
132
 
131
133
  export class BinaryTree<
132
- K = any,
134
+ K extends Comparable,
133
135
  V = any,
134
136
  NODE extends BinaryTreeNode<K, V, NODE> = BinaryTreeNode<K, V, BinaryTreeNodeNested<K, V>>,
135
137
  TREE extends BinaryTree<K, V, NODE, TREE> = BinaryTree<K, V, NODE, BinaryTreeNested<K, V, NODE>>
@@ -147,12 +149,11 @@ export class BinaryTree<
147
149
  * `Partial<BinaryTreeOptions>`, which means that not all properties of `BinaryTreeOptions` are
148
150
  * required.
149
151
  */
150
- constructor(keysOrNodesOrEntries: Iterable<KeyOrNodeOrEntry<K, V, NODE>> = [], options?: BinaryTreeOptions<K>) {
152
+ constructor(keysOrNodesOrEntries: Iterable<KeyOrNodeOrEntry<K, V, NODE>> = [], options?: BinaryTreeOptions) {
151
153
  super();
152
154
  if (options) {
153
- const { iterationType, extractor } = options;
155
+ const { iterationType } = options;
154
156
  if (iterationType) this.iterationType = iterationType;
155
- if (extractor) this._extractor = extractor;
156
157
  }
157
158
 
158
159
  this._size = 0;
@@ -160,16 +161,6 @@ export class BinaryTree<
160
161
  if (keysOrNodesOrEntries) this.addMany(keysOrNodesOrEntries);
161
162
  }
162
163
 
163
- protected _extractor = (key: K) => (typeof key === 'number' ? key : Number(key));
164
-
165
- /**
166
- * The function returns the value of the `_extractor` property.
167
- * @returns The `_extractor` property is being returned.
168
- */
169
- get extractor() {
170
- return this._extractor;
171
- }
172
-
173
164
  protected _root?: NODE | null;
174
165
 
175
166
  /**
@@ -218,7 +209,7 @@ export class BinaryTree<
218
209
  * you can provide only a subset of the properties defined in the `BinaryTreeOptions` interface.
219
210
  * @returns a new instance of a binary tree.
220
211
  */
221
- createTree(options?: Partial<BinaryTreeOptions<K>>): TREE {
212
+ createTree(options?: Partial<BinaryTreeOptions>): TREE {
222
213
  return new BinaryTree<K, V, NODE, TREE>([], { iterationType: this.iterationType, ...options }) as TREE;
223
214
  }
224
215
 
@@ -921,7 +912,7 @@ export class BinaryTree<
921
912
  if (iterationType === 'RECURSIVE') {
922
913
  const dfs = (cur: NODE | null | undefined, min: number, max: number): boolean => {
923
914
  if (!this.isRealNode(cur)) return true;
924
- const numKey = this.extractor(cur.key);
915
+ const numKey = Number(cur.key);
925
916
  if (numKey <= min || numKey >= max) return false;
926
917
  return dfs(cur.left, min, numKey) && dfs(cur.right, numKey, max);
927
918
  };
@@ -941,7 +932,7 @@ export class BinaryTree<
941
932
  curr = curr.left;
942
933
  }
943
934
  curr = stack.pop()!;
944
- const numKey = this.extractor(curr.key);
935
+ const numKey = Number(curr.key);
945
936
  if (!this.isRealNode(curr) || (!checkMax && prev >= numKey) || (checkMax && prev <= numKey)) return false;
946
937
  prev = numKey;
947
938
  curr = curr.right;
@@ -973,15 +964,15 @@ export class BinaryTree<
973
964
  * @returns the depth of the `dist` relative to the `beginRoot`.
974
965
  */
975
966
  getDepth(dist: KeyOrNodeOrEntry<K, V, NODE>, beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root): number {
976
- dist = this.ensureNode(dist);
977
- beginRoot = this.ensureNode(beginRoot);
967
+ let distEnsured = this.ensureNode(dist);
968
+ const beginRootEnsured = this.ensureNode(beginRoot);
978
969
  let depth = 0;
979
- while (dist?.parent) {
980
- if (dist === beginRoot) {
970
+ while (distEnsured?.parent) {
971
+ if (distEnsured === beginRootEnsured) {
981
972
  return depth;
982
973
  }
983
974
  depth++;
984
- dist = dist.parent;
975
+ distEnsured = distEnsured.parent;
985
976
  }
986
977
  return depth;
987
978
  }
@@ -1124,17 +1115,17 @@ export class BinaryTree<
1124
1115
  getPathToRoot(beginNode: KeyOrNodeOrEntry<K, V, NODE>, isReverse = true): NODE[] {
1125
1116
  // TODO to support get path through passing key
1126
1117
  const result: NODE[] = [];
1127
- beginNode = this.ensureNode(beginNode);
1118
+ let beginNodeEnsured = this.ensureNode(beginNode);
1128
1119
 
1129
- if (!beginNode) return result;
1120
+ if (!beginNodeEnsured) return result;
1130
1121
 
1131
- while (beginNode.parent) {
1122
+ while (beginNodeEnsured.parent) {
1132
1123
  // Array.push + Array.reverse is more efficient than Array.unshift
1133
1124
  // TODO may consider using Deque, so far this is not the performance bottleneck
1134
- result.push(beginNode);
1135
- beginNode = beginNode.parent;
1125
+ result.push(beginNodeEnsured);
1126
+ beginNodeEnsured = beginNodeEnsured.parent;
1136
1127
  }
1137
- result.push(beginNode);
1128
+ result.push(beginNodeEnsured);
1138
1129
  return isReverse ? result.reverse() : result;
1139
1130
  }
1140
1131
 
@@ -1840,10 +1831,10 @@ export class BinaryTree<
1840
1831
  console.log(`U for undefined
1841
1832
  `);
1842
1833
  if (opts.isShowNull)
1843
- console.log(`NODE for null
1834
+ console.log(`N for null
1844
1835
  `);
1845
1836
  if (opts.isShowRedBlackNIL)
1846
- console.log(`S for Sentinel Node
1837
+ console.log(`S for Sentinel Node(NIL)
1847
1838
  `);
1848
1839
 
1849
1840
  const display = (root: NODE | null | undefined): void => {
@@ -1873,24 +1864,24 @@ export class BinaryTree<
1873
1864
  let current: NODE | null | undefined = node;
1874
1865
 
1875
1866
  while (current || stack.length > 0) {
1876
- while (current && !isNaN(this.extractor(current.key))) {
1867
+ while (this.isRealNode(current)) {
1877
1868
  stack.push(current);
1878
1869
  current = current.left;
1879
1870
  }
1880
1871
 
1881
1872
  current = stack.pop();
1882
1873
 
1883
- if (current && !isNaN(this.extractor(current.key))) {
1874
+ if (this.isRealNode(current)) {
1884
1875
  yield [current.key, current.value];
1885
1876
  current = current.right;
1886
1877
  }
1887
1878
  }
1888
1879
  } else {
1889
- if (node.left && !isNaN(this.extractor(node.key))) {
1880
+ if (node.left && this.isRealNode(node)) {
1890
1881
  yield* this[Symbol.iterator](node.left);
1891
1882
  }
1892
1883
  yield [node.key, node.value];
1893
- if (node.right && !isNaN(this.extractor(node.key))) {
1884
+ if (node.right && this.isRealNode(node)) {
1894
1885
  yield* this[Symbol.iterator](node.right);
1895
1886
  }
1896
1887
  }
@@ -1919,13 +1910,13 @@ export class BinaryTree<
1919
1910
  return emptyDisplayLayout;
1920
1911
  } else if (node === undefined && !isShowUndefined) {
1921
1912
  return emptyDisplayLayout;
1922
- } else if (node !== null && node !== undefined && isNaN(this.extractor(node.key)) && !isShowRedBlackNIL) {
1913
+ } else if (this.isNIL(node) && !isShowRedBlackNIL) {
1923
1914
  return emptyDisplayLayout;
1924
1915
  } else if (node !== null && node !== undefined) {
1925
1916
  // Display logic of normal nodes
1926
1917
 
1927
1918
  const key = node.key,
1928
- line = isNaN(this.extractor(key)) ? 'S' : this.extractor(key).toString(),
1919
+ line = this.isNIL(node) ? 'S' : key.toString(),
1929
1920
  width = line.length;
1930
1921
 
1931
1922
  return _buildNodeDisplay(