heap-typed 2.0.5 → 2.1.0
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/base/iterable-element-base.d.ts +186 -83
- package/dist/data-structures/base/iterable-element-base.js +149 -107
- package/dist/data-structures/base/iterable-entry-base.d.ts +95 -119
- package/dist/data-structures/base/iterable-entry-base.js +59 -116
- package/dist/data-structures/base/linear-base.d.ts +250 -192
- package/dist/data-structures/base/linear-base.js +137 -274
- package/dist/data-structures/binary-tree/avl-tree-counter.d.ts +126 -158
- package/dist/data-structures/binary-tree/avl-tree-counter.js +171 -205
- package/dist/data-structures/binary-tree/avl-tree-multi-map.d.ts +100 -69
- package/dist/data-structures/binary-tree/avl-tree-multi-map.js +135 -87
- package/dist/data-structures/binary-tree/avl-tree.d.ts +138 -149
- package/dist/data-structures/binary-tree/avl-tree.js +208 -195
- package/dist/data-structures/binary-tree/binary-tree.d.ts +476 -632
- package/dist/data-structures/binary-tree/binary-tree.js +598 -869
- package/dist/data-structures/binary-tree/bst.d.ts +258 -306
- package/dist/data-structures/binary-tree/bst.js +505 -481
- package/dist/data-structures/binary-tree/red-black-tree.d.ts +107 -179
- package/dist/data-structures/binary-tree/red-black-tree.js +114 -209
- package/dist/data-structures/binary-tree/tree-counter.d.ts +132 -154
- package/dist/data-structures/binary-tree/tree-counter.js +172 -203
- package/dist/data-structures/binary-tree/tree-multi-map.d.ts +72 -69
- package/dist/data-structures/binary-tree/tree-multi-map.js +105 -85
- package/dist/data-structures/graph/abstract-graph.d.ts +238 -233
- package/dist/data-structures/graph/abstract-graph.js +267 -237
- package/dist/data-structures/graph/directed-graph.d.ts +108 -224
- package/dist/data-structures/graph/directed-graph.js +146 -233
- package/dist/data-structures/graph/map-graph.d.ts +49 -55
- package/dist/data-structures/graph/map-graph.js +56 -59
- package/dist/data-structures/graph/undirected-graph.d.ts +103 -146
- package/dist/data-structures/graph/undirected-graph.js +129 -149
- package/dist/data-structures/hash/hash-map.d.ts +164 -338
- package/dist/data-structures/hash/hash-map.js +270 -457
- package/dist/data-structures/heap/heap.d.ts +214 -289
- package/dist/data-structures/heap/heap.js +340 -349
- package/dist/data-structures/heap/max-heap.d.ts +11 -47
- package/dist/data-structures/heap/max-heap.js +11 -66
- package/dist/data-structures/heap/min-heap.d.ts +12 -47
- package/dist/data-structures/heap/min-heap.js +11 -66
- package/dist/data-structures/linked-list/doubly-linked-list.d.ts +231 -347
- package/dist/data-structures/linked-list/doubly-linked-list.js +368 -494
- package/dist/data-structures/linked-list/singly-linked-list.d.ts +261 -310
- package/dist/data-structures/linked-list/singly-linked-list.js +447 -466
- package/dist/data-structures/linked-list/skip-linked-list.d.ts +0 -107
- package/dist/data-structures/linked-list/skip-linked-list.js +0 -100
- package/dist/data-structures/priority-queue/max-priority-queue.d.ts +12 -56
- package/dist/data-structures/priority-queue/max-priority-queue.js +11 -78
- package/dist/data-structures/priority-queue/min-priority-queue.d.ts +11 -57
- package/dist/data-structures/priority-queue/min-priority-queue.js +10 -79
- package/dist/data-structures/priority-queue/priority-queue.d.ts +2 -61
- package/dist/data-structures/priority-queue/priority-queue.js +8 -83
- package/dist/data-structures/queue/deque.d.ts +227 -254
- package/dist/data-structures/queue/deque.js +309 -348
- package/dist/data-structures/queue/queue.d.ts +180 -201
- package/dist/data-structures/queue/queue.js +265 -248
- package/dist/data-structures/stack/stack.d.ts +124 -102
- package/dist/data-structures/stack/stack.js +181 -125
- package/dist/data-structures/trie/trie.d.ts +164 -165
- package/dist/data-structures/trie/trie.js +189 -172
- package/dist/interfaces/binary-tree.d.ts +56 -6
- package/dist/interfaces/graph.d.ts +16 -0
- package/dist/types/data-structures/base/base.d.ts +1 -1
- package/dist/types/data-structures/graph/abstract-graph.d.ts +4 -0
- package/dist/types/utils/utils.d.ts +1 -0
- package/dist/utils/utils.d.ts +1 -1
- package/dist/utils/utils.js +2 -1
- package/package.json +2 -2
- package/src/data-structures/base/iterable-element-base.ts +238 -115
- package/src/data-structures/base/iterable-entry-base.ts +96 -120
- package/src/data-structures/base/linear-base.ts +271 -277
- package/src/data-structures/binary-tree/avl-tree-counter.ts +198 -216
- package/src/data-structures/binary-tree/avl-tree-multi-map.ts +192 -101
- package/src/data-structures/binary-tree/avl-tree.ts +239 -206
- package/src/data-structures/binary-tree/binary-tree.ts +664 -893
- package/src/data-structures/binary-tree/bst.ts +568 -570
- package/src/data-structures/binary-tree/red-black-tree.ts +161 -222
- package/src/data-structures/binary-tree/tree-counter.ts +199 -218
- package/src/data-structures/binary-tree/tree-multi-map.ts +131 -97
- package/src/data-structures/graph/abstract-graph.ts +339 -264
- package/src/data-structures/graph/directed-graph.ts +146 -236
- package/src/data-structures/graph/map-graph.ts +63 -60
- package/src/data-structures/graph/undirected-graph.ts +129 -152
- package/src/data-structures/hash/hash-map.ts +274 -496
- package/src/data-structures/heap/heap.ts +389 -402
- package/src/data-structures/heap/max-heap.ts +12 -76
- package/src/data-structures/heap/min-heap.ts +13 -76
- package/src/data-structures/linked-list/doubly-linked-list.ts +426 -530
- package/src/data-structures/linked-list/singly-linked-list.ts +495 -517
- package/src/data-structures/linked-list/skip-linked-list.ts +1 -108
- package/src/data-structures/priority-queue/max-priority-queue.ts +12 -87
- package/src/data-structures/priority-queue/min-priority-queue.ts +11 -88
- package/src/data-structures/priority-queue/priority-queue.ts +3 -92
- package/src/data-structures/queue/deque.ts +381 -357
- package/src/data-structures/queue/queue.ts +310 -264
- package/src/data-structures/stack/stack.ts +217 -131
- package/src/data-structures/trie/trie.ts +240 -175
- package/src/interfaces/binary-tree.ts +240 -6
- package/src/interfaces/graph.ts +37 -0
- package/src/types/data-structures/base/base.ts +5 -5
- package/src/types/data-structures/graph/abstract-graph.ts +5 -0
- package/src/types/utils/utils.ts +2 -0
- package/src/utils/utils.ts +9 -14
|
@@ -5,11 +5,22 @@
|
|
|
5
5
|
* @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>
|
|
6
6
|
* @license MIT License
|
|
7
7
|
*/
|
|
8
|
-
|
|
8
|
+
|
|
9
|
+
import type {
|
|
10
|
+
DequeOptions,
|
|
11
|
+
ElementCallback,
|
|
12
|
+
IterableElementBaseOptions,
|
|
13
|
+
IterableWithSizeOrLength,
|
|
14
|
+
LinearBaseOptions
|
|
15
|
+
} from '../../types';
|
|
9
16
|
import { calcMinUnitsRequired, rangeCheck } from '../../utils';
|
|
10
17
|
import { LinearBase } from '../base/linear-base';
|
|
11
18
|
|
|
12
19
|
/**
|
|
20
|
+
* Deque implemented with circular buckets allowing O(1) amortized push/pop at both ends.
|
|
21
|
+
* @remarks Time O(1), Space O(1)
|
|
22
|
+
* @template E
|
|
23
|
+
* @template R
|
|
13
24
|
* 1. Operations at Both Ends: Supports adding and removing elements at both the front and back of the queue. This allows it to be used as a stack (last in, first out) and a queue (first in, first out).
|
|
14
25
|
* 2. Efficient Random Access: Being based on an array, it offers fast random access capability, allowing constant time access to any element.
|
|
15
26
|
* 3. Continuous Memory Allocation: Since it is based on an array, all elements are stored contiguously in memory, which can bring cache friendliness and efficient memory access.
|
|
@@ -105,17 +116,16 @@ import { LinearBase } from '../base/linear-base';
|
|
|
105
116
|
* console.log(maxSlidingWindow(nums, k)); // [3, 3, 5, 5, 6, 7]
|
|
106
117
|
*/
|
|
107
118
|
export class Deque<E = any, R = any> extends LinearBase<E, R> {
|
|
119
|
+
protected _equals: (a: E, b: E) => boolean = Object.is as unknown as (a: E, b: E) => boolean;
|
|
120
|
+
|
|
108
121
|
/**
|
|
109
|
-
*
|
|
110
|
-
* @
|
|
111
|
-
* elements
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
* @param {DequeOptions} [options] - The `options` parameter is an optional object that can contain
|
|
115
|
-
* configuration options for the deque. In this code, it is used to set the `bucketSize` option,
|
|
116
|
-
* which determines the size of each bucket in the deque. If the `bucketSize` option is not provided
|
|
117
|
-
* or is not a number
|
|
122
|
+
* Create a Deque and optionally bulk-insert elements.
|
|
123
|
+
* @remarks Time O(N), Space O(N)
|
|
124
|
+
* @param [elements] - Iterable (or iterable-like) of elements/records to insert.
|
|
125
|
+
* @param [options] - Options such as bucketSize, toElementFn, and maxLen.
|
|
126
|
+
* @returns New Deque instance.
|
|
118
127
|
*/
|
|
128
|
+
|
|
119
129
|
constructor(elements: IterableWithSizeOrLength<E> | IterableWithSizeOrLength<R> = [], options?: DequeOptions<E, R>) {
|
|
120
130
|
super(options);
|
|
121
131
|
|
|
@@ -126,11 +136,9 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
|
|
|
126
136
|
|
|
127
137
|
let _size: number;
|
|
128
138
|
if ('length' in elements) {
|
|
129
|
-
|
|
130
|
-
else _size = elements.length;
|
|
139
|
+
_size = typeof elements.length === 'function' ? elements.length() : elements.length;
|
|
131
140
|
} else {
|
|
132
|
-
|
|
133
|
-
else _size = elements.size;
|
|
141
|
+
_size = typeof elements.size === 'function' ? elements.size() : elements.size;
|
|
134
142
|
}
|
|
135
143
|
|
|
136
144
|
this._bucketCount = calcMinUnitsRequired(_size, this._bucketSize) || 1;
|
|
@@ -145,80 +153,151 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
|
|
|
145
153
|
|
|
146
154
|
protected _bucketSize: number = 1 << 12;
|
|
147
155
|
|
|
156
|
+
/**
|
|
157
|
+
* Get the current bucket size.
|
|
158
|
+
* @remarks Time O(1), Space O(1)
|
|
159
|
+
* @returns Bucket capacity per bucket.
|
|
160
|
+
*/
|
|
161
|
+
|
|
148
162
|
get bucketSize() {
|
|
149
163
|
return this._bucketSize;
|
|
150
164
|
}
|
|
151
165
|
|
|
152
166
|
protected _bucketFirst = 0;
|
|
153
167
|
|
|
168
|
+
/**
|
|
169
|
+
* Get the index of the first bucket in use.
|
|
170
|
+
* @remarks Time O(1), Space O(1)
|
|
171
|
+
* @returns Zero-based bucket index.
|
|
172
|
+
*/
|
|
173
|
+
|
|
154
174
|
get bucketFirst(): number {
|
|
155
175
|
return this._bucketFirst;
|
|
156
176
|
}
|
|
157
177
|
|
|
158
178
|
protected _firstInBucket = 0;
|
|
159
179
|
|
|
180
|
+
/**
|
|
181
|
+
* Get the index inside the first bucket.
|
|
182
|
+
* @remarks Time O(1), Space O(1)
|
|
183
|
+
* @returns Zero-based index within the first bucket.
|
|
184
|
+
*/
|
|
185
|
+
|
|
160
186
|
get firstInBucket(): number {
|
|
161
187
|
return this._firstInBucket;
|
|
162
188
|
}
|
|
163
189
|
|
|
164
190
|
protected _bucketLast = 0;
|
|
165
191
|
|
|
192
|
+
/**
|
|
193
|
+
* Get the index of the last bucket in use.
|
|
194
|
+
* @remarks Time O(1), Space O(1)
|
|
195
|
+
* @returns Zero-based bucket index.
|
|
196
|
+
*/
|
|
197
|
+
|
|
166
198
|
get bucketLast(): number {
|
|
167
199
|
return this._bucketLast;
|
|
168
200
|
}
|
|
169
201
|
|
|
170
202
|
protected _lastInBucket = 0;
|
|
171
203
|
|
|
204
|
+
/**
|
|
205
|
+
* Get the index inside the last bucket.
|
|
206
|
+
* @remarks Time O(1), Space O(1)
|
|
207
|
+
* @returns Zero-based index within the last bucket.
|
|
208
|
+
*/
|
|
209
|
+
|
|
172
210
|
get lastInBucket(): number {
|
|
173
211
|
return this._lastInBucket;
|
|
174
212
|
}
|
|
175
213
|
|
|
176
214
|
protected _bucketCount = 0;
|
|
177
215
|
|
|
216
|
+
/**
|
|
217
|
+
* Get the number of buckets allocated.
|
|
218
|
+
* @remarks Time O(1), Space O(1)
|
|
219
|
+
* @returns Bucket count.
|
|
220
|
+
*/
|
|
221
|
+
|
|
178
222
|
get bucketCount(): number {
|
|
179
223
|
return this._bucketCount;
|
|
180
224
|
}
|
|
181
225
|
|
|
182
226
|
protected _buckets: E[][] = [];
|
|
183
227
|
|
|
228
|
+
/**
|
|
229
|
+
* Get the internal buckets array.
|
|
230
|
+
* @remarks Time O(1), Space O(1)
|
|
231
|
+
* @returns Array of buckets storing values.
|
|
232
|
+
*/
|
|
233
|
+
|
|
184
234
|
get buckets() {
|
|
185
235
|
return this._buckets;
|
|
186
236
|
}
|
|
187
237
|
|
|
188
238
|
protected _length = 0;
|
|
189
239
|
|
|
240
|
+
/**
|
|
241
|
+
* Get the number of elements in the deque.
|
|
242
|
+
* @remarks Time O(1), Space O(1)
|
|
243
|
+
* @returns Current length.
|
|
244
|
+
*/
|
|
245
|
+
|
|
190
246
|
get length() {
|
|
191
247
|
return this._length;
|
|
192
248
|
}
|
|
193
249
|
|
|
194
250
|
/**
|
|
195
|
-
*
|
|
196
|
-
*
|
|
197
|
-
* @returns
|
|
251
|
+
* Get the first element without removing it.
|
|
252
|
+
* @remarks Time O(1), Space O(1)
|
|
253
|
+
* @returns First element or undefined.
|
|
198
254
|
*/
|
|
255
|
+
|
|
199
256
|
get first(): E | undefined {
|
|
200
257
|
if (this._length === 0) return;
|
|
201
258
|
return this._buckets[this._bucketFirst][this._firstInBucket];
|
|
202
259
|
}
|
|
203
260
|
|
|
204
261
|
/**
|
|
205
|
-
*
|
|
206
|
-
* @
|
|
262
|
+
* Get the last element without removing it.
|
|
263
|
+
* @remarks Time O(1), Space O(1)
|
|
264
|
+
* @returns Last element or undefined.
|
|
207
265
|
*/
|
|
266
|
+
|
|
208
267
|
get last(): E | undefined {
|
|
209
268
|
if (this._length === 0) return;
|
|
210
269
|
return this._buckets[this._bucketLast][this._lastInBucket];
|
|
211
270
|
}
|
|
212
271
|
|
|
213
272
|
/**
|
|
214
|
-
*
|
|
215
|
-
*
|
|
216
|
-
*
|
|
217
|
-
*
|
|
218
|
-
* @param
|
|
219
|
-
*
|
|
220
|
-
* @
|
|
273
|
+
* Create a Deque from an array of elements.
|
|
274
|
+
* @remarks Time O(N), Space O(N)
|
|
275
|
+
* @template E
|
|
276
|
+
* @template R
|
|
277
|
+
* @param this - Constructor (subclass) to instantiate.
|
|
278
|
+
* @param data - Array of elements to insert in order.
|
|
279
|
+
* @param [options] - Options forwarded to the constructor.
|
|
280
|
+
* @returns A new Deque populated from the array.
|
|
221
281
|
*/
|
|
282
|
+
|
|
283
|
+
static fromArray<E, R = any>(
|
|
284
|
+
this: new (
|
|
285
|
+
elements?: IterableWithSizeOrLength<E> | IterableWithSizeOrLength<R>,
|
|
286
|
+
options?: DequeOptions<E, R>
|
|
287
|
+
) => any,
|
|
288
|
+
data: E[],
|
|
289
|
+
options?: DequeOptions<E, R>
|
|
290
|
+
) {
|
|
291
|
+
return new this(data, options);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Append one element at the back.
|
|
296
|
+
* @remarks Time O(1) amortized, Space O(1)
|
|
297
|
+
* @param element - Element to append.
|
|
298
|
+
* @returns True when appended.
|
|
299
|
+
*/
|
|
300
|
+
|
|
222
301
|
push(element: E): boolean {
|
|
223
302
|
if (this._length) {
|
|
224
303
|
if (this._lastInBucket < this._bucketSize - 1) {
|
|
@@ -239,13 +318,11 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
|
|
|
239
318
|
}
|
|
240
319
|
|
|
241
320
|
/**
|
|
242
|
-
*
|
|
243
|
-
*
|
|
244
|
-
*
|
|
245
|
-
* The `pop()` function removes and returns the last element from a data structure, updating the
|
|
246
|
-
* internal state variables accordingly.
|
|
247
|
-
* @returns The element that was removed from the data structure is being returned.
|
|
321
|
+
* Remove and return the last element.
|
|
322
|
+
* @remarks Time O(1), Space O(1)
|
|
323
|
+
* @returns Removed element or undefined.
|
|
248
324
|
*/
|
|
325
|
+
|
|
249
326
|
pop(): E | undefined {
|
|
250
327
|
if (this._length === 0) return;
|
|
251
328
|
const element = this._buckets[this._bucketLast][this._lastInBucket];
|
|
@@ -265,14 +342,11 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
|
|
|
265
342
|
}
|
|
266
343
|
|
|
267
344
|
/**
|
|
268
|
-
*
|
|
269
|
-
*
|
|
270
|
-
*
|
|
271
|
-
* The `shift()` function removes and returns the first element from a data structure, updating the
|
|
272
|
-
* internal state variables accordingly.
|
|
273
|
-
* @returns The element that is being removed from the beginning of the data structure is being
|
|
274
|
-
* returned.
|
|
345
|
+
* Remove and return the first element.
|
|
346
|
+
* @remarks Time O(1) amortized, Space O(1)
|
|
347
|
+
* @returns Removed element or undefined.
|
|
275
348
|
*/
|
|
349
|
+
|
|
276
350
|
shift(): E | undefined {
|
|
277
351
|
if (this._length === 0) return;
|
|
278
352
|
const element = this._buckets[this._bucketFirst][this._firstInBucket];
|
|
@@ -292,15 +366,12 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
|
|
|
292
366
|
}
|
|
293
367
|
|
|
294
368
|
/**
|
|
295
|
-
*
|
|
296
|
-
*
|
|
297
|
-
*
|
|
298
|
-
*
|
|
299
|
-
* returns the new size of the structure.
|
|
300
|
-
* @param {E} element - The `element` parameter represents the element that you want to add to the
|
|
301
|
-
* beginning of the data structure.
|
|
302
|
-
* @returns The size of the data structure after the element has been added.
|
|
369
|
+
* Prepend one element at the front.
|
|
370
|
+
* @remarks Time O(1) amortized, Space O(1)
|
|
371
|
+
* @param element - Element to prepend.
|
|
372
|
+
* @returns True when prepended.
|
|
303
373
|
*/
|
|
374
|
+
|
|
304
375
|
unshift(element: E): boolean {
|
|
305
376
|
if (this._length) {
|
|
306
377
|
if (this._firstInBucket > 0) {
|
|
@@ -321,19 +392,12 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
|
|
|
321
392
|
}
|
|
322
393
|
|
|
323
394
|
/**
|
|
324
|
-
*
|
|
325
|
-
*
|
|
326
|
-
*
|
|
327
|
-
*
|
|
328
|
-
* transformation function if provided.
|
|
329
|
-
* @param {IterableWithSizeOrLength<E> | IterableWithSizeOrLength<R>} elements - The `elements`
|
|
330
|
-
* parameter in the `pushMany` function is expected to be an iterable containing elements of type `E`
|
|
331
|
-
* or `R`. It can be either an `IterableWithSizeOrLength<E>` or an `IterableWithSizeOrLength<R>`. The
|
|
332
|
-
* function iterates over each element
|
|
333
|
-
* @returns The `pushMany` function is returning an array of boolean values, where each value
|
|
334
|
-
* represents the result of calling the `push` method on the current object instance with the
|
|
335
|
-
* corresponding element from the input `elements` iterable.
|
|
395
|
+
* Append a sequence of elements.
|
|
396
|
+
* @remarks Time O(N), Space O(1)
|
|
397
|
+
* @param elements - Iterable (or iterable-like) of elements/records.
|
|
398
|
+
* @returns Array of per-element success flags.
|
|
336
399
|
*/
|
|
400
|
+
|
|
337
401
|
pushMany(elements: IterableWithSizeOrLength<E> | IterableWithSizeOrLength<R>) {
|
|
338
402
|
const ans: boolean[] = [];
|
|
339
403
|
for (const el of elements) {
|
|
@@ -347,18 +411,12 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
|
|
|
347
411
|
}
|
|
348
412
|
|
|
349
413
|
/**
|
|
350
|
-
*
|
|
351
|
-
*
|
|
352
|
-
*
|
|
353
|
-
*
|
|
354
|
-
* an array, optionally converting them using a provided function.
|
|
355
|
-
* @param {IterableWithSizeOrLength<E> | IterableWithSizeOrLength<R>} elements - The `elements`
|
|
356
|
-
* parameter in the `unshiftMany` function is an iterable containing elements of type `E` or `R`. It
|
|
357
|
-
* can be an array or any other iterable data structure that has a known size or length. The function
|
|
358
|
-
* iterates over each element in the `elements` iterable and
|
|
359
|
-
* @returns The `unshiftMany` function returns an array of boolean values indicating whether each
|
|
360
|
-
* element was successfully added to the beginning of the array.
|
|
414
|
+
* Prepend a sequence of elements.
|
|
415
|
+
* @remarks Time O(N), Space O(1)
|
|
416
|
+
* @param [elements] - Iterable (or iterable-like) of elements/records.
|
|
417
|
+
* @returns Array of per-element success flags.
|
|
361
418
|
*/
|
|
419
|
+
|
|
362
420
|
unshiftMany(elements: IterableWithSizeOrLength<E> | IterableWithSizeOrLength<R> = []) {
|
|
363
421
|
const ans: boolean[] = [];
|
|
364
422
|
for (const el of elements) {
|
|
@@ -372,23 +430,21 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
|
|
|
372
430
|
}
|
|
373
431
|
|
|
374
432
|
/**
|
|
375
|
-
*
|
|
376
|
-
*
|
|
377
|
-
*
|
|
378
|
-
* The function checks if the size of an object is equal to zero and returns a boolean value.
|
|
379
|
-
* @returns A boolean value indicating whether the size of the object is 0 or not.
|
|
433
|
+
* Check whether the deque is empty.
|
|
434
|
+
* @remarks Time O(1), Space O(1)
|
|
435
|
+
* @returns True if length is 0.
|
|
380
436
|
*/
|
|
437
|
+
|
|
381
438
|
isEmpty(): boolean {
|
|
382
439
|
return this._length === 0;
|
|
383
440
|
}
|
|
384
441
|
|
|
385
442
|
/**
|
|
386
|
-
*
|
|
387
|
-
*
|
|
388
|
-
*
|
|
389
|
-
* The clear() function resets the state of the object by initializing all variables to their default
|
|
390
|
-
* values.
|
|
443
|
+
* Remove all elements and reset structure.
|
|
444
|
+
* @remarks Time O(1), Space O(1)
|
|
445
|
+
* @returns void
|
|
391
446
|
*/
|
|
447
|
+
|
|
392
448
|
clear(): void {
|
|
393
449
|
this._buckets = [new Array(this._bucketSize)];
|
|
394
450
|
this._bucketCount = 1;
|
|
@@ -397,31 +453,26 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
|
|
|
397
453
|
}
|
|
398
454
|
|
|
399
455
|
/**
|
|
400
|
-
*
|
|
401
|
-
*
|
|
402
|
-
*
|
|
403
|
-
*
|
|
404
|
-
* @param {number} pos - The `pos` parameter represents the position of the element that you want to
|
|
405
|
-
* retrieve from the data structure. It is of type `number` and should be a valid index within the
|
|
406
|
-
* range of the data structure.
|
|
407
|
-
* @returns The element at the specified position in the data structure is being returned.
|
|
456
|
+
* Get the element at a given position.
|
|
457
|
+
* @remarks Time O(1), Space O(1)
|
|
458
|
+
* @param pos - Zero-based position from the front.
|
|
459
|
+
* @returns Element or undefined.
|
|
408
460
|
*/
|
|
409
|
-
|
|
410
|
-
|
|
461
|
+
|
|
462
|
+
at(pos: number): E | undefined {
|
|
463
|
+
if (pos < 0 || pos >= this._length) return undefined;
|
|
411
464
|
const { bucketIndex, indexInBucket } = this._getBucketAndPosition(pos);
|
|
412
|
-
return this._buckets[bucketIndex][indexInBucket]
|
|
465
|
+
return this._buckets[bucketIndex][indexInBucket];
|
|
413
466
|
}
|
|
414
467
|
|
|
415
468
|
/**
|
|
416
|
-
*
|
|
417
|
-
*
|
|
418
|
-
*
|
|
419
|
-
*
|
|
420
|
-
* @
|
|
421
|
-
* set. It is of type `number`.
|
|
422
|
-
* @param {E} element - The `element` parameter is the value that you want to set at the specified
|
|
423
|
-
* position in the data structure.
|
|
469
|
+
* Replace the element at a given position.
|
|
470
|
+
* @remarks Time O(1), Space O(1)
|
|
471
|
+
* @param pos - Zero-based position from the front.
|
|
472
|
+
* @param element - New element value.
|
|
473
|
+
* @returns True if updated.
|
|
424
474
|
*/
|
|
475
|
+
|
|
425
476
|
setAt(pos: number, element: E): boolean {
|
|
426
477
|
rangeCheck(pos, 0, this._length - 1);
|
|
427
478
|
const { bucketIndex, indexInBucket } = this._getBucketAndPosition(pos);
|
|
@@ -430,20 +481,14 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
|
|
|
430
481
|
}
|
|
431
482
|
|
|
432
483
|
/**
|
|
433
|
-
*
|
|
434
|
-
*
|
|
435
|
-
*
|
|
436
|
-
*
|
|
437
|
-
*
|
|
438
|
-
* @
|
|
439
|
-
* be inserted. It is of type `number`.
|
|
440
|
-
* @param {E} element - The `element` parameter represents the element that you want to insert into
|
|
441
|
-
* the array at the specified position.
|
|
442
|
-
* @param [num=1] - The `num` parameter represents the number of times the `element` should be
|
|
443
|
-
* inserted at the specified position (`pos`). By default, it is set to 1, meaning that the `element`
|
|
444
|
-
* will be inserted once. However, you can provide a different value for `num` if you want
|
|
445
|
-
* @returns The size of the array after the insertion is being returned.
|
|
484
|
+
* Insert repeated copies of an element at a position.
|
|
485
|
+
* @remarks Time O(N), Space O(1)
|
|
486
|
+
* @param pos - Zero-based position from the front.
|
|
487
|
+
* @param element - Element to insert.
|
|
488
|
+
* @param [num] - Number of times to insert (default 1).
|
|
489
|
+
* @returns True if inserted.
|
|
446
490
|
*/
|
|
491
|
+
|
|
447
492
|
addAt(pos: number, element: E, num = 1): boolean {
|
|
448
493
|
const length = this._length;
|
|
449
494
|
rangeCheck(pos, 0, length);
|
|
@@ -454,7 +499,8 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
|
|
|
454
499
|
} else {
|
|
455
500
|
const arr: E[] = [];
|
|
456
501
|
for (let i = pos; i < this._length; ++i) {
|
|
457
|
-
|
|
502
|
+
const v = this.at(i);
|
|
503
|
+
if (v !== undefined) arr.push(v);
|
|
458
504
|
}
|
|
459
505
|
this.cut(pos - 1, true);
|
|
460
506
|
for (let i = 0; i < num; ++i) this.push(element);
|
|
@@ -464,16 +510,13 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
|
|
|
464
510
|
}
|
|
465
511
|
|
|
466
512
|
/**
|
|
467
|
-
*
|
|
468
|
-
*
|
|
469
|
-
*
|
|
470
|
-
*
|
|
471
|
-
*
|
|
472
|
-
* @param {number} pos - The `pos` parameter represents the position at which the string should be
|
|
473
|
-
* cut. It is a number that indicates the index of the character where the cut should be made.
|
|
474
|
-
* @param {boolean} isCutSelf - If true, the original deque will not be cut, and return a new deque
|
|
475
|
-
* @returns The method is returning the updated size of the data structure.
|
|
513
|
+
* Cut the deque to keep items up to index; optionally mutate in-place.
|
|
514
|
+
* @remarks Time O(N), Space O(1)
|
|
515
|
+
* @param pos - Last index to keep.
|
|
516
|
+
* @param [isCutSelf] - When true, mutate this deque; otherwise return a new deque.
|
|
517
|
+
* @returns This deque if in-place; otherwise a new deque of the prefix.
|
|
476
518
|
*/
|
|
519
|
+
|
|
477
520
|
cut(pos: number, isCutSelf = false): Deque<E> {
|
|
478
521
|
if (isCutSelf) {
|
|
479
522
|
if (pos < 0) {
|
|
@@ -486,14 +529,11 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
|
|
|
486
529
|
this._length = pos + 1;
|
|
487
530
|
return this;
|
|
488
531
|
} else {
|
|
489
|
-
const newDeque = this._createInstance({
|
|
490
|
-
|
|
491
|
-
toElementFn: this._toElementFn,
|
|
492
|
-
maxLen: this._maxLen
|
|
493
|
-
});
|
|
494
|
-
|
|
532
|
+
const newDeque = this._createInstance({ toElementFn: this._toElementFn, maxLen: this._maxLen });
|
|
533
|
+
newDeque._setBucketSize(this._bucketSize);
|
|
495
534
|
for (let i = 0; i <= pos; i++) {
|
|
496
|
-
|
|
535
|
+
const v = this.at(i);
|
|
536
|
+
if (v !== undefined) newDeque.push(v);
|
|
497
537
|
}
|
|
498
538
|
|
|
499
539
|
return newDeque;
|
|
@@ -501,75 +541,49 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
|
|
|
501
541
|
}
|
|
502
542
|
|
|
503
543
|
/**
|
|
504
|
-
*
|
|
505
|
-
*
|
|
506
|
-
*
|
|
507
|
-
*
|
|
508
|
-
*
|
|
509
|
-
* @
|
|
510
|
-
* to start changing the array. Items will be removed or added starting from this index.
|
|
511
|
-
* @param {number} deleteCount - The `deleteCount` parameter in the `splice` method represents the
|
|
512
|
-
* number of elements to remove from the array starting at the specified `start` index. If
|
|
513
|
-
* `deleteCount` is not provided, it defaults to the number of elements from the `start` index to the
|
|
514
|
-
* end of the array (`
|
|
515
|
-
* @param {E[]} items - The `items` parameter in the `splice` method represents the elements that
|
|
516
|
-
* will be inserted into the deque at the specified `start` index. These elements will be inserted in
|
|
517
|
-
* place of the elements that are removed based on the `start` and `deleteCount` parameters.
|
|
518
|
-
* @returns The `splice` method is returning the array `deletedElements` which contains the elements
|
|
519
|
-
* that were removed from the Deque during the splice operation.
|
|
544
|
+
* Remove and/or insert elements at a position (array-like behavior).
|
|
545
|
+
* @remarks Time O(N + M), Space O(M)
|
|
546
|
+
* @param start - Start index (clamped to [0, length]).
|
|
547
|
+
* @param [deleteCount] - Number of elements to remove (default: length - start).
|
|
548
|
+
* @param [items] - Elements to insert after `start`.
|
|
549
|
+
* @returns A new deque containing the removed elements (typed as `this`).
|
|
520
550
|
*/
|
|
551
|
+
|
|
521
552
|
override splice(start: number, deleteCount: number = this._length - start, ...items: E[]): this {
|
|
522
|
-
// Check whether the starting position is legal
|
|
523
553
|
rangeCheck(start, 0, this._length);
|
|
524
|
-
|
|
525
|
-
// Adjust the value of deleteCount
|
|
526
554
|
if (deleteCount < 0) deleteCount = 0;
|
|
527
555
|
if (start + deleteCount > this._length) deleteCount = this._length - start;
|
|
528
556
|
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
// Add removed elements to the result
|
|
557
|
+
const removed = this._createInstance({ toElementFn: this._toElementFn, maxLen: this._maxLen });
|
|
558
|
+
removed._setBucketSize(this._bucketSize);
|
|
533
559
|
for (let i = 0; i < deleteCount; i++) {
|
|
534
|
-
|
|
560
|
+
const v = this.at(start + i);
|
|
561
|
+
if (v !== undefined) removed.push(v);
|
|
535
562
|
}
|
|
536
563
|
|
|
537
|
-
|
|
538
|
-
const elementsAfter = [];
|
|
564
|
+
const tail: E[] = [];
|
|
539
565
|
for (let i = start + deleteCount; i < this._length; i++) {
|
|
540
|
-
|
|
566
|
+
const v = this.at(i);
|
|
567
|
+
if (v !== undefined) tail.push(v);
|
|
541
568
|
}
|
|
542
569
|
|
|
543
|
-
// Adjust the length of the current Deque
|
|
544
570
|
this.cut(start - 1, true);
|
|
545
571
|
|
|
546
|
-
for (const
|
|
547
|
-
this.push(item);
|
|
548
|
-
}
|
|
572
|
+
for (const it of items) this.push(it);
|
|
549
573
|
|
|
550
|
-
|
|
551
|
-
for (const element of elementsAfter) {
|
|
552
|
-
this.push(element);
|
|
553
|
-
}
|
|
574
|
+
for (const v of tail) this.push(v);
|
|
554
575
|
|
|
555
|
-
return
|
|
576
|
+
return removed as unknown as this;
|
|
556
577
|
}
|
|
557
578
|
|
|
558
579
|
/**
|
|
559
|
-
*
|
|
560
|
-
*
|
|
561
|
-
*
|
|
562
|
-
*
|
|
563
|
-
* deque
|
|
564
|
-
* @param {number} pos - The `pos` parameter represents the position from which to cut the Deque. It
|
|
565
|
-
* is a number that indicates the index of the element in the Deque where the cut should start.
|
|
566
|
-
* @param [isCutSelf=false] - isCutSelf is a boolean parameter that determines whether the original
|
|
567
|
-
* Deque should be modified or a new Deque should be created. If isCutSelf is true, the original
|
|
568
|
-
* Deque will be modified by cutting off elements starting from the specified position. If isCutSelf
|
|
569
|
-
* is false, a new De
|
|
570
|
-
* @returns The function `cutRest` returns either the modified original deque (`this`) or a new deque
|
|
571
|
-
* (`newDeque`) depending on the value of the `isCutSelf` parameter.
|
|
580
|
+
* Cut the deque to keep items from index onward; optionally mutate in-place.
|
|
581
|
+
* @remarks Time O(N), Space O(1)
|
|
582
|
+
* @param pos - First index to keep.
|
|
583
|
+
* @param [isCutSelf] - When true, mutate this deque; otherwise return a new deque.
|
|
584
|
+
* @returns This deque if in-place; otherwise a new deque of the suffix.
|
|
572
585
|
*/
|
|
586
|
+
|
|
573
587
|
cutRest(pos: number, isCutSelf = false): Deque<E> {
|
|
574
588
|
if (isCutSelf) {
|
|
575
589
|
if (pos < 0) {
|
|
@@ -581,45 +595,35 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
|
|
|
581
595
|
this._length = this._length - pos;
|
|
582
596
|
return this;
|
|
583
597
|
} else {
|
|
584
|
-
const newDeque = this._createInstance({
|
|
585
|
-
|
|
586
|
-
toElementFn: this._toElementFn,
|
|
587
|
-
maxLen: this._maxLen
|
|
588
|
-
});
|
|
598
|
+
const newDeque = this._createInstance({ toElementFn: this._toElementFn, maxLen: this._maxLen });
|
|
599
|
+
newDeque._setBucketSize(this._bucketSize);
|
|
589
600
|
if (pos < 0) pos = 0;
|
|
590
601
|
for (let i = pos; i < this._length; i++) {
|
|
591
|
-
|
|
602
|
+
const v = this.at(i);
|
|
603
|
+
if (v !== undefined) newDeque.push(v);
|
|
592
604
|
}
|
|
593
|
-
|
|
594
605
|
return newDeque;
|
|
595
606
|
}
|
|
596
607
|
}
|
|
597
608
|
|
|
598
609
|
/**
|
|
599
|
-
*
|
|
600
|
-
*
|
|
601
|
-
*
|
|
602
|
-
*
|
|
603
|
-
* structure.
|
|
604
|
-
* @param {number} pos - The `pos` parameter in the `deleteAt` function represents the position at
|
|
605
|
-
* which an element needs to be deleted from the data structure. It is of type `number` and indicates
|
|
606
|
-
* the index of the element to be deleted.
|
|
607
|
-
* @returns The size of the data structure after the deletion operation is performed.
|
|
610
|
+
* Delete the element at a given position.
|
|
611
|
+
* @remarks Time O(N), Space O(1)
|
|
612
|
+
* @param pos - Zero-based position from the front.
|
|
613
|
+
* @returns Removed element or undefined.
|
|
608
614
|
*/
|
|
615
|
+
|
|
609
616
|
deleteAt(pos: number): E | undefined {
|
|
610
617
|
rangeCheck(pos, 0, this._length - 1);
|
|
611
618
|
|
|
612
619
|
let deleted: E | undefined;
|
|
613
620
|
if (pos === 0) {
|
|
614
|
-
//If it is the first element, use shift() directly
|
|
615
621
|
return this.shift();
|
|
616
622
|
} else if (pos === this._length - 1) {
|
|
617
|
-
// If it is the last element, just use pop()
|
|
618
623
|
deleted = this.last;
|
|
619
624
|
this.pop();
|
|
620
625
|
return deleted;
|
|
621
626
|
} else {
|
|
622
|
-
// Delete the middle element
|
|
623
627
|
const length = this._length - 1;
|
|
624
628
|
const { bucketIndex: targetBucket, indexInBucket: targetPointer } = this._getBucketAndPosition(pos);
|
|
625
629
|
deleted = this._buckets[targetBucket][targetPointer];
|
|
@@ -630,22 +634,18 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
|
|
|
630
634
|
this._buckets[curBucket][curPointer] = this._buckets[nextBucket][nextPointer];
|
|
631
635
|
}
|
|
632
636
|
|
|
633
|
-
// Remove last duplicate element
|
|
634
637
|
this.pop();
|
|
635
638
|
return deleted;
|
|
636
639
|
}
|
|
637
640
|
}
|
|
638
641
|
|
|
639
642
|
/**
|
|
640
|
-
*
|
|
641
|
-
*
|
|
642
|
-
*
|
|
643
|
-
*
|
|
644
|
-
* structure.
|
|
645
|
-
* @param {E} element - The `element` parameter represents the element that you want to delete from
|
|
646
|
-
* the data structure.
|
|
647
|
-
* @returns The size of the data structure after the element has been deleted.
|
|
643
|
+
* Delete the first occurrence of a value.
|
|
644
|
+
* @remarks Time O(N), Space O(1)
|
|
645
|
+
* @param element - Element to remove (using the configured equality).
|
|
646
|
+
* @returns True if an element was removed.
|
|
648
647
|
*/
|
|
648
|
+
|
|
649
649
|
delete(element: E): boolean {
|
|
650
650
|
const size = this._length;
|
|
651
651
|
if (size === 0) return false;
|
|
@@ -653,7 +653,7 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
|
|
|
653
653
|
let index = 0;
|
|
654
654
|
while (i < size) {
|
|
655
655
|
const oldElement = this.at(i);
|
|
656
|
-
if (oldElement
|
|
656
|
+
if (!this._equals(oldElement as E, element)) {
|
|
657
657
|
this.setAt(index, oldElement!);
|
|
658
658
|
index += 1;
|
|
659
659
|
}
|
|
@@ -663,52 +663,42 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
|
|
|
663
663
|
return true;
|
|
664
664
|
}
|
|
665
665
|
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
// return -1;
|
|
701
|
-
// }
|
|
702
|
-
|
|
703
|
-
/**
|
|
704
|
-
* Time Complexity: O(n)
|
|
705
|
-
* Space Complexity: O(1)
|
|
706
|
-
*
|
|
707
|
-
* The reverse() function reverses the order of the buckets and the elements within each bucket in a
|
|
708
|
-
* data structure.
|
|
709
|
-
* @returns The reverse() method is returning the object itself (this) after performing the reverse
|
|
710
|
-
* operation on the buckets and updating the relevant properties.
|
|
666
|
+
/**
|
|
667
|
+
* Delete the first element matching a predicate.
|
|
668
|
+
* @remarks Time O(N), Space O(1)
|
|
669
|
+
* @param predicate - Function (value, index, deque) → boolean.
|
|
670
|
+
* @returns True if a match was removed.
|
|
671
|
+
*/
|
|
672
|
+
|
|
673
|
+
deleteWhere(predicate: (value: E, index: number, deque: this) => boolean): boolean {
|
|
674
|
+
for (let i = 0; i < this._length; i++) {
|
|
675
|
+
const v = this.at(i);
|
|
676
|
+
if (predicate(v as E, i, this)) {
|
|
677
|
+
this.deleteAt(i);
|
|
678
|
+
return true;
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
return false;
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
/**
|
|
685
|
+
* Set the equality comparator used by delete operations.
|
|
686
|
+
* @remarks Time O(1), Space O(1)
|
|
687
|
+
* @param equals - Equality predicate (a, b) → boolean.
|
|
688
|
+
* @returns This deque.
|
|
689
|
+
*/
|
|
690
|
+
|
|
691
|
+
setEquality(equals: (a: E, b: E) => boolean): this {
|
|
692
|
+
this._equals = equals;
|
|
693
|
+
return this;
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
/**
|
|
697
|
+
* Reverse the deque by reversing buckets and pointers.
|
|
698
|
+
* @remarks Time O(N), Space O(N)
|
|
699
|
+
* @returns This deque.
|
|
711
700
|
*/
|
|
701
|
+
|
|
712
702
|
reverse(): this {
|
|
713
703
|
this._buckets.reverse().forEach(function (bucket) {
|
|
714
704
|
bucket.reverse();
|
|
@@ -722,13 +712,11 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
|
|
|
722
712
|
}
|
|
723
713
|
|
|
724
714
|
/**
|
|
725
|
-
*
|
|
726
|
-
*
|
|
727
|
-
*
|
|
728
|
-
* The `unique()` function removes duplicate elements from an array-like data structure and returns
|
|
729
|
-
* the number of unique elements.
|
|
730
|
-
* @returns The size of the modified array is being returned.
|
|
715
|
+
* Deduplicate consecutive equal elements in-place.
|
|
716
|
+
* @remarks Time O(N), Space O(1)
|
|
717
|
+
* @returns This deque.
|
|
731
718
|
*/
|
|
719
|
+
|
|
732
720
|
unique(): this {
|
|
733
721
|
if (this._length <= 1) {
|
|
734
722
|
return this;
|
|
@@ -737,9 +725,9 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
|
|
|
737
725
|
let prev = this.at(0);
|
|
738
726
|
for (let i = 1; i < this._length; ++i) {
|
|
739
727
|
const cur = this.at(i);
|
|
740
|
-
if (cur
|
|
728
|
+
if (!this._equals(cur as E, prev as E)) {
|
|
741
729
|
prev = cur;
|
|
742
|
-
this.setAt(index++, cur);
|
|
730
|
+
this.setAt(index++, cur as E);
|
|
743
731
|
}
|
|
744
732
|
}
|
|
745
733
|
this.cut(index - 1, true);
|
|
@@ -747,17 +735,14 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
|
|
|
747
735
|
}
|
|
748
736
|
|
|
749
737
|
/**
|
|
750
|
-
*
|
|
751
|
-
*
|
|
752
|
-
*
|
|
753
|
-
* The `shrinkToFit` function reorganizes the elements in an array-like data structure to minimize
|
|
754
|
-
* memory usage.
|
|
755
|
-
* @returns Nothing is being returned. The function is using the `return` statement to exit early if
|
|
756
|
-
* `this._length` is 0, but it does not return any value.
|
|
738
|
+
* Trim unused buckets to fit exactly the active range.
|
|
739
|
+
* @remarks Time O(N), Space O(1)
|
|
740
|
+
* @returns void
|
|
757
741
|
*/
|
|
742
|
+
|
|
758
743
|
shrinkToFit(): void {
|
|
759
744
|
if (this._length === 0) return;
|
|
760
|
-
const newBuckets = [];
|
|
745
|
+
const newBuckets = [] as E[][];
|
|
761
746
|
if (this._bucketFirst === this._bucketLast) return;
|
|
762
747
|
else if (this._bucketFirst < this._bucketLast) {
|
|
763
748
|
for (let i = this._bucketFirst; i <= this._bucketLast; ++i) {
|
|
@@ -777,16 +762,13 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
|
|
|
777
762
|
}
|
|
778
763
|
|
|
779
764
|
/**
|
|
780
|
-
*
|
|
781
|
-
*
|
|
782
|
-
*
|
|
783
|
-
* The `clone()` function returns a new instance of the `Deque` class with the same elements and
|
|
784
|
-
* bucket size as the original instance.
|
|
785
|
-
* @returns The `clone()` method is returning a new instance of the `Deque` class with the same
|
|
786
|
-
* elements as the original deque (`this`) and the same bucket size.
|
|
765
|
+
* Deep clone this deque, preserving options.
|
|
766
|
+
* @remarks Time O(N), Space O(N)
|
|
767
|
+
* @returns A new deque with the same content and options.
|
|
787
768
|
*/
|
|
769
|
+
|
|
788
770
|
clone(): this {
|
|
789
|
-
return
|
|
771
|
+
return this._createLike<E, R>(this, {
|
|
790
772
|
bucketSize: this.bucketSize,
|
|
791
773
|
toElementFn: this.toElementFn,
|
|
792
774
|
maxLen: this._maxLen
|
|
@@ -794,89 +776,106 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
|
|
|
794
776
|
}
|
|
795
777
|
|
|
796
778
|
/**
|
|
797
|
-
*
|
|
798
|
-
*
|
|
799
|
-
*
|
|
800
|
-
*
|
|
801
|
-
*
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
* to be used as `this` when executing the `predicate` function. If `thisArg` is provided, it will be
|
|
808
|
-
* passed as the `this` value to the `predicate` function. If `thisArg` is
|
|
809
|
-
* @returns The `filter` method is returning a new `Deque` object that contains the elements that
|
|
810
|
-
* satisfy the given predicate function.
|
|
811
|
-
*/
|
|
812
|
-
filter(predicate: ElementCallback<E, R, boolean>, thisArg?: any): Deque<E, R> {
|
|
813
|
-
const newDeque = this._createInstance({
|
|
814
|
-
bucketSize: this._bucketSize,
|
|
815
|
-
toElementFn: this.toElementFn,
|
|
816
|
-
maxLen: this._maxLen
|
|
817
|
-
});
|
|
779
|
+
* Filter elements into a new deque of the same class.
|
|
780
|
+
* @remarks Time O(N), Space O(N)
|
|
781
|
+
* @param predicate - Predicate (value, index, deque) → boolean to keep element.
|
|
782
|
+
* @param [thisArg] - Value for `this` inside the predicate.
|
|
783
|
+
* @returns A new deque with kept elements.
|
|
784
|
+
*/
|
|
785
|
+
|
|
786
|
+
filter(predicate: ElementCallback<E, R, boolean>, thisArg?: any): this {
|
|
787
|
+
const out = this._createInstance({ toElementFn: this.toElementFn, maxLen: this._maxLen });
|
|
788
|
+
out._setBucketSize(this._bucketSize);
|
|
818
789
|
let index = 0;
|
|
819
790
|
for (const el of this) {
|
|
820
|
-
if (predicate.call(thisArg, el, index, this))
|
|
821
|
-
newDeque.push(el);
|
|
822
|
-
}
|
|
791
|
+
if (predicate.call(thisArg, el, index, this)) out.push(el);
|
|
823
792
|
index++;
|
|
824
793
|
}
|
|
825
|
-
return
|
|
826
|
-
}
|
|
827
|
-
|
|
828
|
-
/**
|
|
829
|
-
*
|
|
830
|
-
*
|
|
831
|
-
*
|
|
832
|
-
*
|
|
833
|
-
*
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
794
|
+
return out;
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
/**
|
|
798
|
+
* Map elements into a new deque of the same element type.
|
|
799
|
+
* @remarks Time O(N), Space O(N)
|
|
800
|
+
* @param callback - Mapping function (value, index, deque) → newValue.
|
|
801
|
+
* @param [thisArg] - Value for `this` inside the callback.
|
|
802
|
+
* @returns A new deque with mapped values.
|
|
803
|
+
*/
|
|
804
|
+
|
|
805
|
+
mapSame(callback: ElementCallback<E, R, E>, thisArg?: any): this {
|
|
806
|
+
const out = this._createInstance({ toElementFn: this._toElementFn, maxLen: this._maxLen });
|
|
807
|
+
out._setBucketSize(this._bucketSize);
|
|
808
|
+
let index = 0;
|
|
809
|
+
for (const v of this) {
|
|
810
|
+
const mv = thisArg === undefined ? callback(v, index++, this) : callback.call(thisArg, v, index++, this);
|
|
811
|
+
out.push(mv);
|
|
812
|
+
}
|
|
813
|
+
return out;
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
/**
|
|
817
|
+
* Map elements into a new deque (possibly different element type).
|
|
818
|
+
* @remarks Time O(N), Space O(N)
|
|
819
|
+
* @template EM
|
|
820
|
+
* @template RM
|
|
821
|
+
* @param callback - Mapping function (value, index, deque) → newElement.
|
|
822
|
+
* @param [options] - Options for the output deque (e.g., bucketSize, toElementFn, maxLen).
|
|
823
|
+
* @param [thisArg] - Value for `this` inside the callback.
|
|
824
|
+
* @returns A new Deque with mapped elements.
|
|
825
|
+
*/
|
|
826
|
+
|
|
827
|
+
map<EM, RM>(
|
|
828
|
+
callback: ElementCallback<E, R, EM>,
|
|
829
|
+
options?: IterableElementBaseOptions<EM, RM>,
|
|
830
|
+
thisArg?: any
|
|
831
|
+
): Deque<EM, RM> {
|
|
832
|
+
const out = this._createLike<EM, RM>([], {
|
|
833
|
+
...(options ?? {}),
|
|
834
|
+
bucketSize: this._bucketSize,
|
|
835
|
+
maxLen: this._maxLen
|
|
836
|
+
}) as Deque<EM, RM>;
|
|
848
837
|
let index = 0;
|
|
849
838
|
for (const el of this) {
|
|
850
|
-
|
|
839
|
+
const mv = thisArg === undefined ? callback(el, index, this) : callback.call(thisArg, el, index, this);
|
|
840
|
+
out.push(mv);
|
|
851
841
|
index++;
|
|
852
842
|
}
|
|
853
|
-
return
|
|
843
|
+
return out;
|
|
854
844
|
}
|
|
855
845
|
|
|
856
846
|
/**
|
|
857
|
-
*
|
|
858
|
-
*
|
|
859
|
-
*
|
|
860
|
-
*
|
|
861
|
-
* object to be iterated over using a for...of loop.
|
|
847
|
+
* (Protected) Set the internal bucket size.
|
|
848
|
+
* @remarks Time O(1), Space O(1)
|
|
849
|
+
* @param size - Bucket capacity to assign.
|
|
850
|
+
* @returns void
|
|
862
851
|
*/
|
|
852
|
+
|
|
853
|
+
protected _setBucketSize(size: number): void {
|
|
854
|
+
this._bucketSize = size;
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
/**
|
|
858
|
+
* (Protected) Iterate elements from front to back.
|
|
859
|
+
* @remarks Time O(N), Space O(1)
|
|
860
|
+
* @returns Iterator of elements.
|
|
861
|
+
*/
|
|
862
|
+
|
|
863
863
|
protected *_getIterator(): IterableIterator<E> {
|
|
864
864
|
for (let i = 0; i < this._length; ++i) {
|
|
865
|
-
|
|
865
|
+
const v = this.at(i);
|
|
866
|
+
if (v !== undefined) yield v;
|
|
866
867
|
}
|
|
867
868
|
}
|
|
868
869
|
|
|
869
870
|
/**
|
|
870
|
-
*
|
|
871
|
-
*
|
|
872
|
-
*
|
|
873
|
-
*
|
|
874
|
-
* @param {number} [needBucketNum] - The `needBucketNum` parameter is an optional number that
|
|
875
|
-
* specifies the number of new buckets needed. If not provided, it will default to half of the
|
|
876
|
-
* current bucket count (`this._bucketCount >> 1`) or 1 if the current bucket count is less than 2.
|
|
871
|
+
* (Protected) Reallocate buckets to make room near the ends.
|
|
872
|
+
* @remarks Time O(N), Space O(N)
|
|
873
|
+
* @param [needBucketNum] - How many extra buckets to add; defaults to half of current.
|
|
874
|
+
* @returns void
|
|
877
875
|
*/
|
|
876
|
+
|
|
878
877
|
protected _reallocate(needBucketNum?: number) {
|
|
879
|
-
const newBuckets = [];
|
|
878
|
+
const newBuckets = [] as E[][];
|
|
880
879
|
const addBucketNum = needBucketNum || this._bucketCount >> 1 || 1;
|
|
881
880
|
for (let i = 0; i < addBucketNum; ++i) {
|
|
882
881
|
newBuckets[i] = new Array(this._bucketSize);
|
|
@@ -898,14 +897,12 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
|
|
|
898
897
|
}
|
|
899
898
|
|
|
900
899
|
/**
|
|
901
|
-
*
|
|
902
|
-
*
|
|
903
|
-
*
|
|
904
|
-
*
|
|
905
|
-
* @param {number} pos - The `pos` parameter represents the position within the data structure. It is
|
|
906
|
-
* a number that indicates the index or position of an element within the structure.
|
|
907
|
-
* @returns an object with two properties: "bucketIndex" and "indexInBucket".
|
|
900
|
+
* (Protected) Translate a logical position to bucket/offset.
|
|
901
|
+
* @remarks Time O(1), Space O(1)
|
|
902
|
+
* @param pos - Zero-based position.
|
|
903
|
+
* @returns An object containing bucketIndex and indexInBucket.
|
|
908
904
|
*/
|
|
905
|
+
|
|
909
906
|
protected _getBucketAndPosition(pos: number) {
|
|
910
907
|
let bucketIndex: number;
|
|
911
908
|
let indexInBucket: number;
|
|
@@ -926,24 +923,51 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
|
|
|
926
923
|
}
|
|
927
924
|
|
|
928
925
|
/**
|
|
929
|
-
*
|
|
930
|
-
*
|
|
931
|
-
* @param [options] -
|
|
932
|
-
*
|
|
933
|
-
* configuration options when creating a new instance of the `Deque` class.
|
|
934
|
-
* @returns An instance of the `Deque` class with an empty array and the provided options, casted as
|
|
935
|
-
* `this`.
|
|
926
|
+
* (Protected) Create an empty instance of the same concrete class.
|
|
927
|
+
* @remarks Time O(1), Space O(1)
|
|
928
|
+
* @param [options] - Options forwarded to the constructor.
|
|
929
|
+
* @returns An empty like-kind deque instance.
|
|
936
930
|
*/
|
|
937
|
-
|
|
938
|
-
|
|
931
|
+
|
|
932
|
+
protected override _createInstance(options?: LinearBaseOptions<E, R>): this {
|
|
933
|
+
const Ctor = this.constructor as new (
|
|
934
|
+
elements?: IterableWithSizeOrLength<E> | IterableWithSizeOrLength<R>,
|
|
935
|
+
options?: DequeOptions<E, R>
|
|
936
|
+
) => this;
|
|
937
|
+
return new Ctor([], options as DequeOptions<E, R> | undefined);
|
|
939
938
|
}
|
|
940
939
|
|
|
941
940
|
/**
|
|
942
|
-
*
|
|
941
|
+
* (Protected) Create a like-kind deque seeded by elements.
|
|
942
|
+
* @remarks Time O(N), Space O(N)
|
|
943
|
+
* @template T
|
|
944
|
+
* @template RR
|
|
945
|
+
* @param [elements] - Iterable used to seed the new deque.
|
|
946
|
+
* @param [options] - Options forwarded to the constructor.
|
|
947
|
+
* @returns A like-kind Deque instance.
|
|
943
948
|
*/
|
|
949
|
+
|
|
950
|
+
protected _createLike<T = E, RR = R>(
|
|
951
|
+
elements: IterableWithSizeOrLength<T> | IterableWithSizeOrLength<RR> = [],
|
|
952
|
+
options?: DequeOptions<T, RR>
|
|
953
|
+
): any {
|
|
954
|
+
const Ctor = this.constructor as new (
|
|
955
|
+
elements?: IterableWithSizeOrLength<T> | IterableWithSizeOrLength<RR>,
|
|
956
|
+
options?: DequeOptions<T, RR>
|
|
957
|
+
) => any;
|
|
958
|
+
return new Ctor(elements, options);
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
/**
|
|
962
|
+
* (Protected) Iterate elements from back to front.
|
|
963
|
+
* @remarks Time O(N), Space O(1)
|
|
964
|
+
* @returns Iterator of elements.
|
|
965
|
+
*/
|
|
966
|
+
|
|
944
967
|
protected *_getReverseIterator(): IterableIterator<E> {
|
|
945
968
|
for (let i = this._length - 1; i > -1; i--) {
|
|
946
|
-
|
|
969
|
+
const v = this.at(i);
|
|
970
|
+
if (v !== undefined) yield v;
|
|
947
971
|
}
|
|
948
972
|
}
|
|
949
973
|
}
|