deque-typed 1.47.5 → 1.47.7
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/dist/data-structures/binary-tree/avl-tree.d.ts +36 -18
- package/dist/data-structures/binary-tree/avl-tree.js +46 -29
- package/dist/data-structures/binary-tree/binary-tree.d.ts +158 -129
- package/dist/data-structures/binary-tree/binary-tree.js +182 -184
- package/dist/data-structures/binary-tree/bst.d.ts +73 -63
- package/dist/data-structures/binary-tree/bst.js +168 -169
- package/dist/data-structures/binary-tree/rb-tree.d.ts +54 -17
- package/dist/data-structures/binary-tree/rb-tree.js +77 -31
- package/dist/data-structures/binary-tree/tree-multimap.d.ts +29 -40
- package/dist/data-structures/binary-tree/tree-multimap.js +66 -136
- package/dist/data-structures/graph/abstract-graph.js +1 -1
- package/dist/data-structures/hash/hash-map.d.ts +2 -6
- package/dist/data-structures/hash/hash-map.js +5 -8
- package/dist/data-structures/heap/heap.d.ts +19 -21
- package/dist/data-structures/heap/heap.js +52 -34
- package/dist/data-structures/heap/max-heap.d.ts +2 -5
- package/dist/data-structures/heap/max-heap.js +2 -2
- package/dist/data-structures/heap/min-heap.d.ts +2 -5
- package/dist/data-structures/heap/min-heap.js +2 -2
- package/dist/data-structures/linked-list/doubly-linked-list.d.ts +2 -1
- package/dist/data-structures/linked-list/doubly-linked-list.js +9 -1
- package/dist/data-structures/linked-list/singly-linked-list.d.ts +2 -1
- package/dist/data-structures/linked-list/singly-linked-list.js +8 -1
- package/dist/data-structures/priority-queue/max-priority-queue.d.ts +2 -5
- package/dist/data-structures/priority-queue/max-priority-queue.js +2 -2
- package/dist/data-structures/priority-queue/min-priority-queue.d.ts +2 -5
- package/dist/data-structures/priority-queue/min-priority-queue.js +2 -2
- package/dist/data-structures/priority-queue/priority-queue.d.ts +2 -5
- package/dist/data-structures/priority-queue/priority-queue.js +2 -2
- package/dist/data-structures/queue/deque.d.ts +1 -0
- package/dist/data-structures/queue/deque.js +3 -0
- package/dist/data-structures/queue/queue.d.ts +1 -0
- package/dist/data-structures/queue/queue.js +3 -0
- package/dist/data-structures/stack/stack.d.ts +2 -1
- package/dist/data-structures/stack/stack.js +10 -2
- package/dist/data-structures/trie/trie.d.ts +3 -0
- package/dist/data-structures/trie/trie.js +19 -4
- package/dist/interfaces/binary-tree.d.ts +4 -2
- package/dist/types/common.d.ts +7 -0
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +1 -1
- package/dist/types/data-structures/binary-tree/bst.d.ts +2 -2
- package/dist/types/data-structures/hash/hash-map.d.ts +1 -2
- package/dist/types/data-structures/heap/heap.d.ts +4 -1
- package/dist/types/data-structures/priority-queue/priority-queue.d.ts +2 -1
- package/package.json +2 -2
- package/src/data-structures/binary-tree/avl-tree.ts +61 -31
- package/src/data-structures/binary-tree/binary-tree.ts +283 -254
- package/src/data-structures/binary-tree/bst.ts +193 -170
- package/src/data-structures/binary-tree/rb-tree.ts +87 -32
- package/src/data-structures/binary-tree/tree-multimap.ts +76 -136
- package/src/data-structures/graph/abstract-graph.ts +1 -1
- package/src/data-structures/hash/hash-map.ts +8 -8
- package/src/data-structures/heap/heap.ts +57 -39
- package/src/data-structures/heap/max-heap.ts +5 -5
- package/src/data-structures/heap/min-heap.ts +5 -5
- package/src/data-structures/linked-list/doubly-linked-list.ts +10 -1
- package/src/data-structures/linked-list/singly-linked-list.ts +9 -1
- package/src/data-structures/priority-queue/max-priority-queue.ts +4 -3
- package/src/data-structures/priority-queue/min-priority-queue.ts +12 -12
- package/src/data-structures/priority-queue/priority-queue.ts +3 -3
- package/src/data-structures/queue/deque.ts +4 -0
- package/src/data-structures/queue/queue.ts +4 -0
- package/src/data-structures/stack/stack.ts +12 -3
- package/src/data-structures/trie/trie.ts +23 -4
- package/src/interfaces/binary-tree.ts +14 -2
- package/src/types/common.ts +15 -1
- package/src/types/data-structures/binary-tree/binary-tree.ts +1 -1
- package/src/types/data-structures/binary-tree/bst.ts +2 -3
- package/src/types/data-structures/hash/hash-map.ts +1 -2
- package/src/types/data-structures/heap/heap.ts +3 -1
- package/src/types/data-structures/priority-queue/priority-queue.ts +3 -1
|
@@ -5,7 +5,17 @@
|
|
|
5
5
|
* @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>
|
|
6
6
|
* @license MIT License
|
|
7
7
|
*/
|
|
8
|
-
import type {
|
|
8
|
+
import type {
|
|
9
|
+
BSTNested,
|
|
10
|
+
BSTNodeKeyOrNode,
|
|
11
|
+
BSTNodeNested,
|
|
12
|
+
BSTOptions,
|
|
13
|
+
BTNCallback,
|
|
14
|
+
BTNKey,
|
|
15
|
+
BTNodeExemplar,
|
|
16
|
+
BTNodePureExemplar,
|
|
17
|
+
Comparator
|
|
18
|
+
} from '../../types';
|
|
9
19
|
import { CP, IterationType } from '../../types';
|
|
10
20
|
import { BinaryTree, BinaryTreeNode } from './binary-tree';
|
|
11
21
|
import { IBinaryTree } from '../../interfaces';
|
|
@@ -62,36 +72,51 @@ export class BSTNode<V = any, N extends BSTNode<V, N> = BSTNodeNested<V>> extend
|
|
|
62
72
|
}
|
|
63
73
|
}
|
|
64
74
|
|
|
75
|
+
/**
|
|
76
|
+
* 1. Node Order: Each node's left child has a lesser value, and the right child has a greater value.
|
|
77
|
+
* 2. Unique Keys: No duplicate keys in a standard BST.
|
|
78
|
+
* 3. Efficient Search: Enables quick search, minimum, and maximum operations.
|
|
79
|
+
* 4. Inorder Traversal: Yields nodes in ascending order.
|
|
80
|
+
* 5. Logarithmic Operations: Ideal operations like insertion, deletion, and searching are O(log n) time-efficient.
|
|
81
|
+
* 6. Balance Variability: Can become unbalanced; special types maintain balance.
|
|
82
|
+
* 7. No Auto-Balancing: Standard BSTs don't automatically balance themselves.
|
|
83
|
+
*/
|
|
65
84
|
export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>, TREE extends BST<V, N, TREE> = BST<V, N, BSTNested<V, N>>>
|
|
66
85
|
extends BinaryTree<V, N, TREE>
|
|
67
86
|
implements IBinaryTree<V, N, TREE> {
|
|
68
87
|
|
|
69
|
-
override options: BSTOptions;
|
|
70
88
|
|
|
71
89
|
/**
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
90
|
+
* This is the constructor function for a binary search tree class in TypeScript, which initializes
|
|
91
|
+
* the tree with optional elements and options.
|
|
92
|
+
* @param [elements] - An optional iterable of BTNodeExemplar objects that will be added to the
|
|
93
|
+
* binary search tree.
|
|
94
|
+
* @param [options] - The `options` parameter is an optional object that can contain additional
|
|
95
|
+
* configuration options for the binary search tree. It can have the following properties:
|
|
75
96
|
*/
|
|
76
|
-
constructor(options?: BSTOptions) {
|
|
77
|
-
super(options);
|
|
97
|
+
constructor(elements?: Iterable<BTNodeExemplar<V, N>>, options?: Partial<BSTOptions>) {
|
|
98
|
+
super([], options);
|
|
99
|
+
|
|
78
100
|
if (options) {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
101
|
+
const { comparator } = options;
|
|
102
|
+
if (comparator) {
|
|
103
|
+
this.comparator = comparator;
|
|
104
|
+
}
|
|
82
105
|
}
|
|
106
|
+
|
|
83
107
|
this._root = undefined;
|
|
108
|
+
|
|
109
|
+
if (elements) this.addMany(elements);
|
|
84
110
|
}
|
|
85
111
|
|
|
86
112
|
protected override _root?: N;
|
|
87
113
|
|
|
88
|
-
/**
|
|
89
|
-
* Get the root node of the binary tree.
|
|
90
|
-
*/
|
|
91
114
|
override get root(): N | undefined {
|
|
92
115
|
return this._root;
|
|
93
116
|
}
|
|
94
117
|
|
|
118
|
+
comparator: Comparator<BTNKey> = (a, b) => a - b
|
|
119
|
+
|
|
95
120
|
/**
|
|
96
121
|
* The function creates a new binary search tree node with the given key and value.
|
|
97
122
|
* @param {BTNKey} key - The key parameter is the key value that will be associated with
|
|
@@ -104,8 +129,18 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
104
129
|
return new BSTNode<V, N>(key, value) as N;
|
|
105
130
|
}
|
|
106
131
|
|
|
107
|
-
|
|
108
|
-
|
|
132
|
+
/**
|
|
133
|
+
* The function creates a new binary search tree with the specified options.
|
|
134
|
+
* @param [options] - The `options` parameter is an optional object that allows you to customize the
|
|
135
|
+
* behavior of the `createTree` method. It accepts a partial `BSTOptions` object, which is a type
|
|
136
|
+
* that defines various options for creating a binary search tree.
|
|
137
|
+
* @returns a new instance of the BST class with the specified options.
|
|
138
|
+
*/
|
|
139
|
+
override createTree(options?: Partial<BSTOptions>): TREE {
|
|
140
|
+
return new BST<V, N, TREE>([], {
|
|
141
|
+
iterationType: this.iterationType,
|
|
142
|
+
comparator: this.comparator, ...options
|
|
143
|
+
}) as TREE;
|
|
109
144
|
}
|
|
110
145
|
|
|
111
146
|
/**
|
|
@@ -117,158 +152,145 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
117
152
|
* Time Complexity: O(log n) - Average case for a balanced tree. In the worst case (unbalanced tree), it can be O(n).
|
|
118
153
|
* Space Complexity: O(1) - Constant space is used.
|
|
119
154
|
*
|
|
120
|
-
* The `add` function adds a new node to a binary search tree
|
|
121
|
-
*
|
|
122
|
-
* following
|
|
123
|
-
* @
|
|
124
|
-
*
|
|
125
|
-
* @returns The method `add` returns a node (`N`) that was inserted into the binary search tree. If
|
|
126
|
-
* no node was inserted, it returns `undefined`.
|
|
155
|
+
* The `add` function adds a new node to a binary search tree, either by key or by providing a node
|
|
156
|
+
* object.
|
|
157
|
+
* @param keyOrNodeOrEntry - The `keyOrNodeOrEntry` parameter can be one of the following:
|
|
158
|
+
* @returns The method returns either the newly added node (`newNode`) or `undefined` if the input
|
|
159
|
+
* (`keyOrNodeOrEntry`) is null, undefined, or does not match any of the expected types.
|
|
127
160
|
*/
|
|
128
|
-
override add(
|
|
129
|
-
if (
|
|
130
|
-
|
|
131
|
-
|
|
161
|
+
override add(keyOrNodeOrEntry: BTNodeExemplar<V, N>): N | undefined {
|
|
162
|
+
if (keyOrNodeOrEntry === null || keyOrNodeOrEntry === undefined) {
|
|
163
|
+
return undefined;
|
|
164
|
+
}
|
|
165
|
+
|
|
132
166
|
let newNode: N | undefined;
|
|
133
|
-
if (
|
|
134
|
-
newNode =
|
|
135
|
-
} else if (this.isNodeKey(
|
|
136
|
-
newNode = this.createNode(
|
|
167
|
+
if (keyOrNodeOrEntry instanceof BSTNode) {
|
|
168
|
+
newNode = keyOrNodeOrEntry;
|
|
169
|
+
} else if (this.isNodeKey(keyOrNodeOrEntry)) {
|
|
170
|
+
newNode = this.createNode(keyOrNodeOrEntry);
|
|
171
|
+
} else if (this.isEntry(keyOrNodeOrEntry)) {
|
|
172
|
+
const [key, value] = keyOrNodeOrEntry;
|
|
173
|
+
if (key === undefined || key === null) {
|
|
174
|
+
return;
|
|
175
|
+
} else {
|
|
176
|
+
newNode = this.createNode(key, value);
|
|
177
|
+
}
|
|
137
178
|
} else {
|
|
138
|
-
|
|
179
|
+
return;
|
|
139
180
|
}
|
|
181
|
+
|
|
140
182
|
if (this.root === undefined) {
|
|
141
183
|
this._setRoot(newNode);
|
|
142
|
-
this._size
|
|
143
|
-
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
if (newNode) {
|
|
175
|
-
newNode.parent = cur;
|
|
176
|
-
}
|
|
177
|
-
//Add to the right of the current node
|
|
178
|
-
cur.right = newNode;
|
|
179
|
-
this._size = this.size + 1;
|
|
180
|
-
traversing = false;
|
|
181
|
-
inserted = cur.right;
|
|
182
|
-
} else {
|
|
183
|
-
//Traverse the left of the current node
|
|
184
|
-
if (cur.right) cur = cur.right;
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
} else {
|
|
188
|
-
traversing = false;
|
|
184
|
+
this._size++;
|
|
185
|
+
return this.root;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
let current = this.root;
|
|
189
|
+
while (current !== undefined) {
|
|
190
|
+
if (this._compare(current.key, newNode.key) === CP.eq) {
|
|
191
|
+
// if (current !== newNode) {
|
|
192
|
+
// The key value is the same but the reference is different, update the value of the existing node
|
|
193
|
+
this._replaceNode(current, newNode);
|
|
194
|
+
return newNode;
|
|
195
|
+
|
|
196
|
+
// } else {
|
|
197
|
+
// The key value is the same and the reference is the same, replace the entire node
|
|
198
|
+
// this._replaceNode(current, newNode);
|
|
199
|
+
|
|
200
|
+
// return;
|
|
201
|
+
// }
|
|
202
|
+
} else if (this._compare(current.key, newNode.key) === CP.gt) {
|
|
203
|
+
if (current.left === undefined) {
|
|
204
|
+
current.left = newNode;
|
|
205
|
+
newNode.parent = current;
|
|
206
|
+
this._size++;
|
|
207
|
+
return newNode;
|
|
208
|
+
}
|
|
209
|
+
current = current.left;
|
|
210
|
+
} else {
|
|
211
|
+
if (current.right === undefined) {
|
|
212
|
+
current.right = newNode;
|
|
213
|
+
newNode.parent = current;
|
|
214
|
+
this._size++;
|
|
215
|
+
return newNode;
|
|
189
216
|
}
|
|
217
|
+
current = current.right;
|
|
190
218
|
}
|
|
191
219
|
}
|
|
192
|
-
|
|
220
|
+
|
|
221
|
+
return undefined;
|
|
193
222
|
}
|
|
194
223
|
|
|
195
224
|
/**
|
|
196
|
-
* Time Complexity: O(
|
|
197
|
-
* Space Complexity: O(
|
|
225
|
+
* Time Complexity: O(k log n) - Adding each element individually in a balanced tree.
|
|
226
|
+
* Space Complexity: O(k) - Additional space is required for the sorted array.
|
|
198
227
|
*/
|
|
199
228
|
|
|
200
229
|
/**
|
|
201
|
-
* Time Complexity: O(
|
|
202
|
-
* Space Complexity: O(
|
|
230
|
+
* Time Complexity: O(k log n) - Adding each element individually in a balanced tree.
|
|
231
|
+
* Space Complexity: O(k) - Additional space is required for the sorted array.
|
|
203
232
|
*
|
|
204
|
-
* The `addMany` function
|
|
205
|
-
*
|
|
206
|
-
* @param
|
|
207
|
-
* binary
|
|
208
|
-
* node), or `undefined`.
|
|
209
|
-
* @param {(V | undefined)[]} [data] - An optional array of values to associate with the keys or
|
|
210
|
-
* nodes being added. If provided, the length of the `data` array must be the same as the length of
|
|
211
|
-
* the `keysOrNodes` array.
|
|
233
|
+
* The `addMany` function in TypeScript adds multiple nodes to a binary tree, either in a balanced or
|
|
234
|
+
* unbalanced manner, and returns an array of the inserted nodes.
|
|
235
|
+
* @param keysOrNodesOrEntries - An iterable containing keys, nodes, or entries to be added to the
|
|
236
|
+
* binary tree.
|
|
212
237
|
* @param [isBalanceAdd=true] - A boolean flag indicating whether the tree should be balanced after
|
|
213
|
-
* adding the nodes. The default value is
|
|
238
|
+
* adding the nodes. The default value is true.
|
|
214
239
|
* @param iterationType - The `iterationType` parameter is an optional parameter that specifies the
|
|
215
|
-
* type of iteration to use when adding multiple keys or nodes to the binary
|
|
216
|
-
*
|
|
217
|
-
*
|
|
218
|
-
* @returns The
|
|
240
|
+
* type of iteration to use when adding multiple keys or nodes to the binary tree. It has a default
|
|
241
|
+
* value of `this.iterationType`, which means it will use the iteration type specified by the binary
|
|
242
|
+
* tree instance.
|
|
243
|
+
* @returns The `addMany` function returns an array of `N` or `undefined` values.
|
|
219
244
|
*/
|
|
220
245
|
override addMany(
|
|
221
|
-
|
|
222
|
-
data?: (V | undefined)[],
|
|
246
|
+
keysOrNodesOrEntries: Iterable<BTNodeExemplar<V, N>>,
|
|
223
247
|
isBalanceAdd = true,
|
|
224
|
-
iterationType = this.
|
|
248
|
+
iterationType = this.iterationType
|
|
225
249
|
): (N | undefined)[] {
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
250
|
+
const inserted: (N | undefined)[] = []
|
|
251
|
+
if (!isBalanceAdd) {
|
|
252
|
+
for (const kve of keysOrNodesOrEntries) {
|
|
253
|
+
const nn = this.add(kve)
|
|
254
|
+
inserted.push(nn);
|
|
255
|
+
}
|
|
256
|
+
return inserted;
|
|
229
257
|
}
|
|
258
|
+
const realBTNExemplars: BTNodePureExemplar<V, N>[] = [];
|
|
230
259
|
|
|
231
|
-
|
|
232
|
-
|
|
260
|
+
const isRealBTNExemplar = (kve: BTNodeExemplar<V, N>): kve is BTNodePureExemplar<V, N> => {
|
|
261
|
+
if (kve === undefined || kve === null) return false;
|
|
262
|
+
return !(this.isEntry(kve) && (kve[0] === undefined || kve[0] === null));
|
|
233
263
|
}
|
|
234
264
|
|
|
235
|
-
const
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
);
|
|
265
|
+
for (const kve of keysOrNodesOrEntries) {
|
|
266
|
+
isRealBTNExemplar(kve) && realBTNExemplars.push(kve);
|
|
267
|
+
}
|
|
239
268
|
|
|
240
|
-
|
|
269
|
+
// TODO this addMany function is inefficient, it should be optimized
|
|
270
|
+
let sorted: BTNodePureExemplar<V, N>[] = [];
|
|
241
271
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
272
|
+
sorted = realBTNExemplars.sort((a, b) => {
|
|
273
|
+
let aR: number, bR: number;
|
|
274
|
+
if (this.isEntry(a)) aR = a[0]
|
|
275
|
+
else if (this.isRealNode(a)) aR = a.key
|
|
276
|
+
else aR = a;
|
|
246
277
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
};
|
|
278
|
+
if (this.isEntry(b)) bR = b[0]
|
|
279
|
+
else if (this.isRealNode(b)) bR = b.key
|
|
280
|
+
else bR = b;
|
|
251
281
|
|
|
252
|
-
|
|
253
|
-
|
|
282
|
+
return aR - bR;
|
|
283
|
+
})
|
|
254
284
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
} else if (_isBinaryTreeKeyOrNullTuple(combinedArr)) {
|
|
258
|
-
sorted = combinedArr.sort((a, b) => a[0] - b[0]);
|
|
259
|
-
} else {
|
|
260
|
-
throw new Error('Invalid input keysOrNodes');
|
|
261
|
-
}
|
|
262
|
-
sortedKeysOrNodes = sorted.map(([keyOrNode]) => keyOrNode);
|
|
263
|
-
sortedData = sorted.map(([, value]) => value);
|
|
264
|
-
const _dfs = (arr: (BTNKey | undefined | N)[], data?: (V | undefined)[]) => {
|
|
285
|
+
|
|
286
|
+
const _dfs = (arr: BTNodePureExemplar<V, N>[]) => {
|
|
265
287
|
if (arr.length === 0) return;
|
|
266
288
|
|
|
267
289
|
const mid = Math.floor((arr.length - 1) / 2);
|
|
268
|
-
const newNode = this.add(arr[mid]
|
|
290
|
+
const newNode = this.add(arr[mid]);
|
|
269
291
|
inserted.push(newNode);
|
|
270
|
-
_dfs(arr.slice(0, mid)
|
|
271
|
-
_dfs(arr.slice(mid + 1)
|
|
292
|
+
_dfs(arr.slice(0, mid));
|
|
293
|
+
_dfs(arr.slice(mid + 1));
|
|
272
294
|
};
|
|
273
295
|
const _iterate = () => {
|
|
274
296
|
const n = sorted.length;
|
|
@@ -279,7 +301,7 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
279
301
|
const [l, r] = popped;
|
|
280
302
|
if (l <= r) {
|
|
281
303
|
const m = l + Math.floor((r - l) / 2);
|
|
282
|
-
const newNode = this.add(
|
|
304
|
+
const newNode = this.add(sorted[m]);
|
|
283
305
|
inserted.push(newNode);
|
|
284
306
|
stack.push([m + 1, r]);
|
|
285
307
|
stack.push([l, m - 1]);
|
|
@@ -288,7 +310,7 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
288
310
|
}
|
|
289
311
|
};
|
|
290
312
|
if (iterationType === IterationType.RECURSIVE) {
|
|
291
|
-
_dfs(
|
|
313
|
+
_dfs(sorted);
|
|
292
314
|
} else {
|
|
293
315
|
_iterate();
|
|
294
316
|
}
|
|
@@ -297,8 +319,8 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
297
319
|
}
|
|
298
320
|
|
|
299
321
|
/**
|
|
300
|
-
* Time Complexity: O(log n) -
|
|
301
|
-
* Space Complexity: O(
|
|
322
|
+
* Time Complexity: O(n log n) - Adding each element individually in a balanced tree.
|
|
323
|
+
* Space Complexity: O(n) - Additional space is required for the sorted array.
|
|
302
324
|
*/
|
|
303
325
|
|
|
304
326
|
/**
|
|
@@ -316,7 +338,7 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
316
338
|
* the key of the leftmost node if the comparison result is greater than, and the key of the
|
|
317
339
|
* rightmost node otherwise. If no node is found, it returns 0.
|
|
318
340
|
*/
|
|
319
|
-
lastKey(beginRoot:
|
|
341
|
+
lastKey(beginRoot: BSTNodeKeyOrNode<N> = this.root, iterationType = this.iterationType): BTNKey {
|
|
320
342
|
if (this._compare(0, 1) === CP.lt) return this.getRightMost(beginRoot, iterationType)?.key ?? 0;
|
|
321
343
|
else if (this._compare(0, 1) === CP.gt) return this.getLeftMost(beginRoot, iterationType)?.key ?? 0;
|
|
322
344
|
else return this.getRightMost(beginRoot, iterationType)?.key ?? 0;
|
|
@@ -324,7 +346,7 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
324
346
|
|
|
325
347
|
/**
|
|
326
348
|
* Time Complexity: O(log n) - Average case for a balanced tree.
|
|
327
|
-
* Space Complexity: O(
|
|
349
|
+
* Space Complexity: O(1) - Constant space is used.
|
|
328
350
|
*/
|
|
329
351
|
|
|
330
352
|
/**
|
|
@@ -367,7 +389,12 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
367
389
|
}
|
|
368
390
|
|
|
369
391
|
/**
|
|
370
|
-
*
|
|
392
|
+
* Time Complexity: O(log n) - Average case for a balanced tree.
|
|
393
|
+
* Space Complexity: O(log n) - Space for the recursive call stack in the worst case.
|
|
394
|
+
*/
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* The function `ensureNode` returns the node corresponding to the given key if it is a node key,
|
|
371
398
|
* otherwise it returns the key itself.
|
|
372
399
|
* @param {BTNKey | N | undefined} key - The `key` parameter can be of type `BTNKey`, `N`, or
|
|
373
400
|
* `undefined`.
|
|
@@ -375,15 +402,10 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
375
402
|
* type of iteration to be performed. It has a default value of `IterationType.ITERATIVE`.
|
|
376
403
|
* @returns either a node object (N) or undefined.
|
|
377
404
|
*/
|
|
378
|
-
override
|
|
405
|
+
override ensureNode(key: BSTNodeKeyOrNode<N>, iterationType = IterationType.ITERATIVE): N | undefined {
|
|
379
406
|
return this.isNodeKey(key) ? this.getNodeByKey(key, iterationType) : key;
|
|
380
407
|
}
|
|
381
408
|
|
|
382
|
-
/**
|
|
383
|
-
* Time Complexity: O(log n) - Average case for a balanced tree. O(n) - Visiting each node once when identifier is not node's key.
|
|
384
|
-
* Space Complexity: O(log n) - Space for the recursive call stack in the worst case.
|
|
385
|
-
*/
|
|
386
|
-
|
|
387
409
|
/**
|
|
388
410
|
* Time Complexity: O(log n) - Average case for a balanced tree. O(n) - Visiting each node once when identifier is not node's key.
|
|
389
411
|
* Space Complexity: O(log n) - Space for the recursive call stack in the worst case.
|
|
@@ -411,10 +433,10 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
411
433
|
identifier: ReturnType<C> | undefined,
|
|
412
434
|
callback: C = this._defaultOneParamCallback as C,
|
|
413
435
|
onlyOne = false,
|
|
414
|
-
beginRoot:
|
|
415
|
-
iterationType = this.
|
|
436
|
+
beginRoot: BSTNodeKeyOrNode<N> = this.root,
|
|
437
|
+
iterationType = this.iterationType
|
|
416
438
|
): N[] {
|
|
417
|
-
beginRoot = this.
|
|
439
|
+
beginRoot = this.ensureNode(beginRoot);
|
|
418
440
|
if (!beginRoot) return [];
|
|
419
441
|
const ans: N[] = [];
|
|
420
442
|
|
|
@@ -492,10 +514,10 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
492
514
|
lesserOrGreaterTraverse<C extends BTNCallback<N>>(
|
|
493
515
|
callback: C = this._defaultOneParamCallback as C,
|
|
494
516
|
lesserOrGreater: CP = CP.lt,
|
|
495
|
-
targetNode:
|
|
496
|
-
iterationType = this.
|
|
517
|
+
targetNode: BSTNodeKeyOrNode<N> = this.root,
|
|
518
|
+
iterationType = this.iterationType
|
|
497
519
|
): ReturnType<C>[] {
|
|
498
|
-
targetNode = this.
|
|
520
|
+
targetNode = this.ensureNode(targetNode);
|
|
499
521
|
const ans: ReturnType<BTNCallback<N>>[] = [];
|
|
500
522
|
if (!targetNode) return ans;
|
|
501
523
|
if (!this.root) return ans;
|
|
@@ -531,18 +553,8 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
531
553
|
}
|
|
532
554
|
|
|
533
555
|
/**
|
|
534
|
-
*
|
|
535
|
-
*
|
|
536
|
-
* AVL Tree: After insertion or deletion operations, an AVL tree performs rotation adjustments based on the balance factor of nodes to restore the tree's balance. These rotations can be left rotations, right rotations, left-right rotations, or right-left rotations, performed as needed.
|
|
537
|
-
*
|
|
538
|
-
* Use Cases and Efficiency:
|
|
539
|
-
* Perfectly Balanced Binary Tree: Perfectly balanced binary trees are typically used in specific scenarios such as complete binary heaps in heap sort or certain types of Huffman trees. However, they are not suitable for dynamic operations requiring frequent insertions and deletions, as these operations often necessitate full tree reconstruction.
|
|
540
|
-
* AVL Tree: AVL trees are well-suited for scenarios involving frequent searching, insertion, and deletion operations. Through rotation adjustments, AVL trees maintain their balance, ensuring average and worst-case time complexity of O(log n).
|
|
541
|
-
*/
|
|
542
|
-
|
|
543
|
-
/**
|
|
544
|
-
* Time Complexity: O(n) - Building a balanced tree from a sorted array.
|
|
545
|
-
* Space Complexity: O(n) - Additional space is required for the sorted array.
|
|
556
|
+
* Time Complexity: O(log n) - Average case for a balanced tree. O(n) - Visiting each node once when identifier is not node's key.
|
|
557
|
+
* Space Complexity: O(log n) - Space for the recursive call stack in the worst case.
|
|
546
558
|
*/
|
|
547
559
|
|
|
548
560
|
/**
|
|
@@ -556,7 +568,7 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
556
568
|
* values:
|
|
557
569
|
* @returns The function `perfectlyBalance` returns a boolean value.
|
|
558
570
|
*/
|
|
559
|
-
perfectlyBalance(iterationType = this.
|
|
571
|
+
perfectlyBalance(iterationType = this.iterationType): boolean {
|
|
560
572
|
const sorted = this.dfs(node => node, 'in'),
|
|
561
573
|
n = sorted.length;
|
|
562
574
|
this.clear();
|
|
@@ -567,7 +579,7 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
567
579
|
if (l > r) return;
|
|
568
580
|
const m = l + Math.floor((r - l) / 2);
|
|
569
581
|
const midNode = sorted[m];
|
|
570
|
-
this.add(midNode.key, midNode.value);
|
|
582
|
+
this.add([midNode.key, midNode.value]);
|
|
571
583
|
buildBalanceBST(l, m - 1);
|
|
572
584
|
buildBalanceBST(m + 1, r);
|
|
573
585
|
};
|
|
@@ -584,7 +596,7 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
584
596
|
const m = l + Math.floor((r - l) / 2);
|
|
585
597
|
const midNode = sorted[m];
|
|
586
598
|
debugger;
|
|
587
|
-
this.add(midNode.key, midNode.value);
|
|
599
|
+
this.add([midNode.key, midNode.value]);
|
|
588
600
|
stack.push([m + 1, r]);
|
|
589
601
|
stack.push([l, m - 1]);
|
|
590
602
|
}
|
|
@@ -595,8 +607,18 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
595
607
|
}
|
|
596
608
|
|
|
597
609
|
/**
|
|
598
|
-
*
|
|
599
|
-
*
|
|
610
|
+
* Balancing Adjustment:
|
|
611
|
+
* Perfectly Balanced Binary Tree: Since the balance of a perfectly balanced binary tree is already fixed, no additional balancing adjustment is needed. Any insertion or deletion operation will disrupt the perfect balance, often requiring a complete reconstruction of the tree.
|
|
612
|
+
* AVL Tree: After insertion or deletion operations, an AVL tree performs rotation adjustments based on the balance factor of nodes to restore the tree's balance. These rotations can be left rotations, right rotations, left-right rotations, or right-left rotations, performed as needed.
|
|
613
|
+
*
|
|
614
|
+
* Use Cases and Efficiency:
|
|
615
|
+
* Perfectly Balanced Binary Tree: Perfectly balanced binary trees are typically used in specific scenarios such as complete binary heaps in heap sort or certain types of Huffman trees. However, they are not suitable for dynamic operations requiring frequent insertions and deletions, as these operations often necessitate full tree reconstruction.
|
|
616
|
+
* AVL Tree: AVL trees are well-suited for scenarios involving frequent searching, insertion, and deletion operations. Through rotation adjustments, AVL trees maintain their balance, ensuring average and worst-case time complexity of O(log n).
|
|
617
|
+
*/
|
|
618
|
+
|
|
619
|
+
/**
|
|
620
|
+
* Time Complexity: O(n) - Building a balanced tree from a sorted array.
|
|
621
|
+
* Space Complexity: O(n) - Additional space is required for the sorted array.
|
|
600
622
|
*/
|
|
601
623
|
|
|
602
624
|
/**
|
|
@@ -608,7 +630,7 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
608
630
|
* to check if the AVL tree is balanced. It can have two possible values:
|
|
609
631
|
* @returns a boolean value.
|
|
610
632
|
*/
|
|
611
|
-
isAVLBalanced(iterationType = this.
|
|
633
|
+
isAVLBalanced(iterationType = this.iterationType): boolean {
|
|
612
634
|
if (!this.root) return true;
|
|
613
635
|
|
|
614
636
|
let balanced = true;
|
|
@@ -652,6 +674,7 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
652
674
|
return balanced;
|
|
653
675
|
}
|
|
654
676
|
|
|
677
|
+
|
|
655
678
|
protected _setRoot(v: N | undefined) {
|
|
656
679
|
if (v) {
|
|
657
680
|
v.parent = undefined;
|
|
@@ -668,7 +691,7 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
668
691
|
* than), CP.lt (less than), or CP.eq (equal).
|
|
669
692
|
*/
|
|
670
693
|
protected _compare(a: BTNKey, b: BTNKey): CP {
|
|
671
|
-
const compared = this.
|
|
694
|
+
const compared = this.comparator(a, b);
|
|
672
695
|
if (compared > 0) return CP.gt;
|
|
673
696
|
else if (compared < 0) return CP.lt;
|
|
674
697
|
else return CP.eq;
|