data-structure-typed 1.46.2 → 1.46.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1 -1
- package/README.md +16 -16
- package/benchmark/report.html +1 -46
- package/benchmark/report.json +16 -385
- package/dist/cjs/data-structures/hash/hash-map.d.ts +10 -91
- package/dist/cjs/data-structures/hash/hash-map.js +22 -178
- package/dist/cjs/data-structures/hash/hash-map.js.map +1 -1
- package/dist/cjs/data-structures/queue/deque.d.ts +6 -74
- package/dist/cjs/data-structures/queue/deque.js +20 -142
- package/dist/cjs/data-structures/queue/deque.js.map +1 -1
- package/dist/mjs/data-structures/hash/hash-map.d.ts +10 -91
- package/dist/mjs/data-structures/hash/hash-map.js +22 -181
- package/dist/mjs/data-structures/queue/deque.d.ts +6 -74
- package/dist/mjs/data-structures/queue/deque.js +16 -140
- package/dist/umd/data-structure-typed.js +73 -349
- package/dist/umd/data-structure-typed.min.js +1 -1
- package/dist/umd/data-structure-typed.min.js.map +1 -1
- package/package.json +4 -3
- package/src/data-structures/hash/hash-map.ts +25 -196
- package/src/data-structures/queue/deque.ts +22 -161
- package/test/performance/data-structures/hash/hash-map.test.ts +11 -11
- package/test/performance/reportor.ts +6 -3
- package/test/unit/data-structures/hash/hash-map.test.ts +4 -5
- package/test/unit/data-structures/queue/deque.test.ts +28 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "data-structure-typed",
|
|
3
|
-
"version": "1.46.
|
|
3
|
+
"version": "1.46.3",
|
|
4
4
|
"description": "Data Structures of Javascript & TypeScript. Binary Tree, BST, Graph, Heap, Priority Queue, Linked List, Queue, Deque, Stack, AVL Tree, Tree Multiset, Trie, Directed Graph, Undirected Graph, Singly Linked List, Doubly Linked List, Max Heap, Max Priority Queue, Min Heap, Min Priority Queue.",
|
|
5
5
|
"main": "dist/cjs/index.js",
|
|
6
6
|
"module": "dist/mjs/index.js",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"test:unit": "jest --runInBand",
|
|
23
23
|
"test": "npm run test:unit",
|
|
24
24
|
"test:integration": "npm run update:subs && jest --config jest.integration.config.js",
|
|
25
|
-
"test:perf": "ts-node test/performance/reportor.ts",
|
|
25
|
+
"test:perf": "npm run build:cjs && npm run build:mjs && ts-node test/performance/reportor.ts",
|
|
26
26
|
"check": "tsc --noEmit",
|
|
27
27
|
"check:circular-refs": "dependency-cruiser src",
|
|
28
28
|
"lint:src": "eslint --fix 'src/**/*.{js,ts}'",
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
"format:src": "prettier --write 'src/**/*.{js,ts}'",
|
|
33
33
|
"format:test": "prettier --write 'test/**/*.{js,ts}'",
|
|
34
34
|
"format": "npm run format:src && npm run format:test",
|
|
35
|
+
"check:exist-latest": "sh scripts/check_exist_remotely.sh",
|
|
35
36
|
"ci": "env && git fetch --tags && npm run inspect && npm run lint && npm run build && npm run test:unit && npm run changelog",
|
|
36
37
|
"update:subs": "npm i avl-tree-typed binary-tree-typed bst-typed heap-typed data-structure-typed --save-dev",
|
|
37
38
|
"install:all-subs": "npm i avl-tree-typed binary-tree-typed bst-typed deque-typed directed-graph-typed doubly-linked-list-typed graph-typed heap-typed linked-list-typed max-heap-typed max-priority-queue-typed min-heap-typed min-priority-queue-typed priority-queue-typed singly-linked-list-typed stack-typed tree-multimap-typed trie-typed undirected-graph-typed queue-typed --save-dev",
|
|
@@ -40,7 +41,7 @@
|
|
|
40
41
|
"copy:to-subs": "sh scripts/copy_to_all_subs.sh",
|
|
41
42
|
"publish:subs": "npm run copy:to-subs && sh scripts/publish_all_subs.sh",
|
|
42
43
|
"publish:docs": "sh scripts/publish_docs.sh",
|
|
43
|
-
"publish:all": "npm run ci && npm publish && npm run publish:docs && npm
|
|
44
|
+
"publish:all": "npm run ci && npm publish && npm run publish:docs && npm run check:exist-latest && npm run publish:subs"
|
|
44
45
|
},
|
|
45
46
|
"repository": {
|
|
46
47
|
"type": "git",
|
|
@@ -6,127 +6,8 @@
|
|
|
6
6
|
* @license MIT License
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import { isObjOrFunc, rangeCheck
|
|
10
|
-
import { HashMapLinkedNode, IterableWithSizeOrLength
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Because the implementation of HashMap relies on JavaScript's built-in objects and arrays,
|
|
14
|
-
* these underlying structures have already dealt with dynamic expansion and hash collisions.
|
|
15
|
-
* Therefore, there is no need for additional logic to handle these issues.
|
|
16
|
-
*/
|
|
17
|
-
export class HashMapIterator<K, V> {
|
|
18
|
-
readonly hashMap: HashMap<K, V>;
|
|
19
|
-
readonly iterateDirection: IterateDirection;
|
|
20
|
-
protected _node: HashMapLinkedNode<K, V>;
|
|
21
|
-
protected readonly _sentinel: HashMapLinkedNode<K, V>;
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* This is a constructor function for a linked list iterator in a HashMap data structure.
|
|
25
|
-
* @param node - The `node` parameter is a reference to a `HashMapLinkedNode` object. This object
|
|
26
|
-
* represents a node in a linked list used in a hash map data structure. It contains a key-value pair
|
|
27
|
-
* and references to the previous and next nodes in the linked list.
|
|
28
|
-
* @param sentinel - The `sentinel` parameter is a reference to a special node in a linked list. It
|
|
29
|
-
* is used to mark the beginning or end of the list and is typically used in data structures like
|
|
30
|
-
* hash maps or linked lists to simplify operations and boundary checks.
|
|
31
|
-
* @param hashMap - A HashMap object that stores key-value pairs.
|
|
32
|
-
* @param {IterateDirection} iterateDirection - The `iterateDirection` parameter is an optional
|
|
33
|
-
* parameter that specifies the direction in which the iterator should iterate over the elements of
|
|
34
|
-
* the HashMap. It can take one of the following values:
|
|
35
|
-
* @returns The constructor does not return anything. It is used to initialize the properties and
|
|
36
|
-
* methods of the object being created.
|
|
37
|
-
*/
|
|
38
|
-
constructor(
|
|
39
|
-
node: HashMapLinkedNode<K, V>,
|
|
40
|
-
sentinel: HashMapLinkedNode<K, V>,
|
|
41
|
-
hashMap: HashMap<K, V>,
|
|
42
|
-
iterateDirection: IterateDirection = IterateDirection.DEFAULT
|
|
43
|
-
) {
|
|
44
|
-
this._node = node;
|
|
45
|
-
this._sentinel = sentinel;
|
|
46
|
-
this.iterateDirection = iterateDirection;
|
|
47
|
-
|
|
48
|
-
if (this.iterateDirection === IterateDirection.DEFAULT) {
|
|
49
|
-
this.prev = function () {
|
|
50
|
-
if (this._node.prev === this._sentinel) {
|
|
51
|
-
throwRangeError();
|
|
52
|
-
}
|
|
53
|
-
this._node = this._node.prev;
|
|
54
|
-
return this;
|
|
55
|
-
};
|
|
56
|
-
this.next = function () {
|
|
57
|
-
if (this._node === this._sentinel) {
|
|
58
|
-
throwRangeError();
|
|
59
|
-
}
|
|
60
|
-
this._node = this._node.next;
|
|
61
|
-
return this;
|
|
62
|
-
};
|
|
63
|
-
} else {
|
|
64
|
-
this.prev = function () {
|
|
65
|
-
if (this._node.next === this._sentinel) {
|
|
66
|
-
throwRangeError();
|
|
67
|
-
}
|
|
68
|
-
this._node = this._node.next;
|
|
69
|
-
return this;
|
|
70
|
-
};
|
|
71
|
-
this.next = function () {
|
|
72
|
-
if (this._node === this._sentinel) {
|
|
73
|
-
throwRangeError();
|
|
74
|
-
}
|
|
75
|
-
this._node = this._node.prev;
|
|
76
|
-
return this;
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
this.hashMap = hashMap;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* The above function returns a Proxy object that allows access to the key and value of a node in a
|
|
84
|
-
* data structure.
|
|
85
|
-
* @returns The code is returning a Proxy object.
|
|
86
|
-
*/
|
|
87
|
-
get current() {
|
|
88
|
-
if (this._node === this._sentinel) {
|
|
89
|
-
throwRangeError();
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
return new Proxy(<[K, V]>(<unknown>[]), {
|
|
93
|
-
get: (target, prop: '0' | '1') => {
|
|
94
|
-
if (prop === '0') return this._node.key;
|
|
95
|
-
else if (prop === '1') return this._node.value;
|
|
96
|
-
target[0] = this._node.key;
|
|
97
|
-
target[1] = this._node.value;
|
|
98
|
-
return target[prop];
|
|
99
|
-
},
|
|
100
|
-
set: (_, prop: '1', newValue: V) => {
|
|
101
|
-
if (prop !== '1') {
|
|
102
|
-
throw new TypeError(`prop should be string '1'`);
|
|
103
|
-
}
|
|
104
|
-
this._node.value = newValue;
|
|
105
|
-
return true;
|
|
106
|
-
}
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* The function checks if a node is accessible.
|
|
112
|
-
* @returns a boolean value indicating whether the `_node` is not equal to the `_sentinel`.
|
|
113
|
-
*/
|
|
114
|
-
isAccessible() {
|
|
115
|
-
return this._node !== this._sentinel;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
prev() {
|
|
119
|
-
return this;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
next() {
|
|
123
|
-
return this;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
clone() {
|
|
127
|
-
return new HashMapIterator<K, V>(this._node, this._sentinel, this.hashMap, this.iterateDirection)
|
|
128
|
-
}
|
|
129
|
-
}
|
|
9
|
+
import { isObjOrFunc, rangeCheck } from '../../utils';
|
|
10
|
+
import { HashMapLinkedNode, IterableWithSizeOrLength } from '../../types';
|
|
130
11
|
|
|
131
12
|
export class HashMap<K = any, V = any> {
|
|
132
13
|
readonly OBJ_KEY_INDEX = Symbol('OBJ_KEY_INDEX');
|
|
@@ -158,53 +39,6 @@ export class HashMap<K = any, V = any> {
|
|
|
158
39
|
return this._size;
|
|
159
40
|
}
|
|
160
41
|
|
|
161
|
-
/**
|
|
162
|
-
* Time Complexity: O(1)
|
|
163
|
-
* Space Complexity: O(1)
|
|
164
|
-
*
|
|
165
|
-
* The function returns a new iterator object for a HashMap.
|
|
166
|
-
* @returns A new instance of the HashMapIterator class is being returned.
|
|
167
|
-
*/
|
|
168
|
-
get begin() {
|
|
169
|
-
return new HashMapIterator<K, V>(this._head, this._sentinel, this);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
/**
|
|
173
|
-
* Time Complexity: O(1)
|
|
174
|
-
* Space Complexity: O(1)
|
|
175
|
-
*
|
|
176
|
-
* The function returns a new HashMapIterator object with the _sentinel value as both the start and
|
|
177
|
-
* end values.
|
|
178
|
-
* @returns A new instance of the HashMapIterator class is being returned.
|
|
179
|
-
*/
|
|
180
|
-
get end() {
|
|
181
|
-
return new HashMapIterator<K, V>(this._sentinel, this._sentinel, this);
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
* Time Complexity: O(1)
|
|
186
|
-
* Space Complexity: O(1)
|
|
187
|
-
*
|
|
188
|
-
* The reverseBegin function returns a new HashMapIterator object that iterates over the elements of
|
|
189
|
-
* a HashMap in reverse order.
|
|
190
|
-
* @returns A new instance of the HashMapIterator class is being returned.
|
|
191
|
-
*/
|
|
192
|
-
get reverseBegin() {
|
|
193
|
-
return new HashMapIterator<K, V>(this._tail, this._sentinel, this, IterateDirection.REVERSE);
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
/**
|
|
197
|
-
* Time Complexity: O(1)
|
|
198
|
-
* Space Complexity: O(1)
|
|
199
|
-
*
|
|
200
|
-
* The reverseEnd function returns a new HashMapIterator object that iterates over the elements of a
|
|
201
|
-
* HashMap in reverse order.
|
|
202
|
-
* @returns A new instance of the HashMapIterator class is being returned.
|
|
203
|
-
*/
|
|
204
|
-
get reverseEnd() {
|
|
205
|
-
return new HashMapIterator<K, V>(this._sentinel, this._sentinel, this, IterateDirection.REVERSE);
|
|
206
|
-
}
|
|
207
|
-
|
|
208
42
|
/**
|
|
209
43
|
* Time Complexity: O(1)
|
|
210
44
|
* Space Complexity: O(1)
|
|
@@ -231,6 +65,29 @@ export class HashMap<K = any, V = any> {
|
|
|
231
65
|
return <[K, V]>[this._tail.key, this._tail.value];
|
|
232
66
|
}
|
|
233
67
|
|
|
68
|
+
/**
|
|
69
|
+
* The `begin()` function in TypeScript iterates over a linked list and yields key-value pairs.
|
|
70
|
+
*/
|
|
71
|
+
* begin() {
|
|
72
|
+
let node = this._head;
|
|
73
|
+
while (node !== this._sentinel) {
|
|
74
|
+
yield [node.key, node.value];
|
|
75
|
+
node = node.next;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* The function `reverseBegin()` iterates over a linked list in reverse order, yielding each node's
|
|
81
|
+
* key and value.
|
|
82
|
+
*/
|
|
83
|
+
* reverseBegin() {
|
|
84
|
+
let node = this._tail;
|
|
85
|
+
while (node !== this._sentinel) {
|
|
86
|
+
yield [node.key, node.value];
|
|
87
|
+
node = node.prev;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
234
91
|
/**
|
|
235
92
|
* Time Complexity: O(1)
|
|
236
93
|
* Space Complexity: O(1)
|
|
@@ -332,34 +189,6 @@ export class HashMap<K = any, V = any> {
|
|
|
332
189
|
return <[K, V]>[node.key, node.value];
|
|
333
190
|
}
|
|
334
191
|
|
|
335
|
-
/**
|
|
336
|
-
* Time Complexity: O(1)
|
|
337
|
-
* Space Complexity: O(1)
|
|
338
|
-
*
|
|
339
|
-
* The function `getIterator` returns a new instance of `HashMapIterator` based on the provided key
|
|
340
|
-
* and whether it is an object key or not.
|
|
341
|
-
* @param {K} key - The `key` parameter is the key used to retrieve the iterator from the HashMap. It
|
|
342
|
-
* can be of any type, depending on how the HashMap is implemented.
|
|
343
|
-
* @param {boolean} [isObjectKey] - The `isObjectKey` parameter is an optional boolean parameter that
|
|
344
|
-
* indicates whether the `key` parameter is an object key. If `isObjectKey` is `true`, it means that
|
|
345
|
-
* the `key` parameter is an object and needs to be handled differently. If `isObjectKey` is `false`
|
|
346
|
-
* @returns a new instance of the `HashMapIterator` class.
|
|
347
|
-
*/
|
|
348
|
-
getIterator(key: K, isObjectKey?: boolean) {
|
|
349
|
-
let node: HashMapLinkedNode<K, V>;
|
|
350
|
-
if (isObjectKey) {
|
|
351
|
-
const index = (<Record<symbol, number>>(<unknown>key))[this.OBJ_KEY_INDEX];
|
|
352
|
-
if (index === undefined) {
|
|
353
|
-
node = this._sentinel;
|
|
354
|
-
} else {
|
|
355
|
-
node = this._nodes[index];
|
|
356
|
-
}
|
|
357
|
-
} else {
|
|
358
|
-
node = this._orgMap[<string>(<unknown>key)] || this._sentinel;
|
|
359
|
-
}
|
|
360
|
-
return new HashMapIterator<K, V>(node, this._sentinel, this);
|
|
361
|
-
}
|
|
362
|
-
|
|
363
192
|
/**
|
|
364
193
|
* Time Complexity: O(1)
|
|
365
194
|
* Space Complexity: O(1)
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
import { IterableWithSizeOrLength
|
|
11
|
-
import { calcMinUnitsRequired, rangeCheck
|
|
10
|
+
import { IterableWithSizeOrLength } from "../../types";
|
|
11
|
+
import { calcMinUnitsRequired, rangeCheck } from "../../utils";
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Deque can provide random access with O(1) time complexity
|
|
@@ -17,89 +17,6 @@ import { calcMinUnitsRequired, rangeCheck, throwRangeError } from "../../utils";
|
|
|
17
17
|
* Deque is implemented using a dynamic array. Inserting or deleting beyond both ends of the array may require moving elements or reallocating space.
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
-
export class DequeIterator<E> {
|
|
21
|
-
iterateDirection: IterateDirection;
|
|
22
|
-
|
|
23
|
-
index: number;
|
|
24
|
-
readonly deque: Deque<E>;
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* The constructor initializes the index, iterate direction, and prev/next functions for a
|
|
28
|
-
* DequeIterator object.
|
|
29
|
-
* @param {number} index - The index parameter represents the current index position of the iterator
|
|
30
|
-
* within the deque. It is a number that indicates the position of the element that the iterator is
|
|
31
|
-
* currently pointing to.
|
|
32
|
-
* @param deque - The `deque` parameter is an instance of the `Deque` class. It represents a
|
|
33
|
-
* double-ended queue data structure, which allows elements to be added or removed from both ends.
|
|
34
|
-
* @param iterateDirection - The `iterateDirection` parameter is an optional parameter that specifies
|
|
35
|
-
* the direction in which the iterator should iterate over the elements of the `deque`. It has a
|
|
36
|
-
* default value of `IterateDirection.DEFAULT`.
|
|
37
|
-
* @returns The constructor is not returning anything. It is used to initialize the properties of the
|
|
38
|
-
* object being created.
|
|
39
|
-
*/
|
|
40
|
-
constructor(index: number, deque: Deque<E>, iterateDirection = IterateDirection.DEFAULT) {
|
|
41
|
-
this.index = index;
|
|
42
|
-
this.iterateDirection = iterateDirection;
|
|
43
|
-
if (this.iterateDirection === IterateDirection.DEFAULT) {
|
|
44
|
-
this.prev = function () {
|
|
45
|
-
if (this.index === 0) {
|
|
46
|
-
throwRangeError();
|
|
47
|
-
}
|
|
48
|
-
this.index -= 1;
|
|
49
|
-
return this;
|
|
50
|
-
};
|
|
51
|
-
this.next = function () {
|
|
52
|
-
if (this.index === this.deque.size) {
|
|
53
|
-
throwRangeError();
|
|
54
|
-
}
|
|
55
|
-
this.index += 1;
|
|
56
|
-
return this;
|
|
57
|
-
};
|
|
58
|
-
} else {
|
|
59
|
-
this.prev = function () {
|
|
60
|
-
if (this.index === this.deque.size - 1) {
|
|
61
|
-
throwRangeError();
|
|
62
|
-
}
|
|
63
|
-
this.index += 1;
|
|
64
|
-
return this;
|
|
65
|
-
};
|
|
66
|
-
this.next = function () {
|
|
67
|
-
if (this.index === -1) {
|
|
68
|
-
throwRangeError();
|
|
69
|
-
}
|
|
70
|
-
this.index -= 1;
|
|
71
|
-
return this;
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
this.deque = deque;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
get current() {
|
|
78
|
-
return this.deque.getAt(this.index);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
set current(newElement: E) {
|
|
82
|
-
this.deque.setAt(this.index, newElement);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
isAccessible() {
|
|
86
|
-
return this.index !== this.deque.size;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
prev(): DequeIterator<E> {
|
|
90
|
-
return this;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
next(): DequeIterator<E> {
|
|
94
|
-
return this;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
clone() {
|
|
98
|
-
return new DequeIterator<E>(this.index, this.deque, this.iterateDirection);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
}
|
|
102
|
-
|
|
103
20
|
export class Deque<E> {
|
|
104
21
|
protected _bucketFirst = 0;
|
|
105
22
|
protected _firstInBucket = 0;
|
|
@@ -123,7 +40,7 @@ export class Deque<E> {
|
|
|
123
40
|
if ('length' in elements) {
|
|
124
41
|
if (elements.length instanceof Function) _size = elements.length(); else _size = elements.length;
|
|
125
42
|
} else {
|
|
126
|
-
if (elements.size instanceof Function) _size = elements.size();else _size = elements.size;
|
|
43
|
+
if (elements.size instanceof Function) _size = elements.size(); else _size = elements.size;
|
|
127
44
|
}
|
|
128
45
|
|
|
129
46
|
this._bucketSize = bucketSize;
|
|
@@ -245,38 +162,26 @@ export class Deque<E> {
|
|
|
245
162
|
}
|
|
246
163
|
|
|
247
164
|
/**
|
|
248
|
-
* The
|
|
249
|
-
* @returns A new instance of the DequeIterator class is being returned.
|
|
250
|
-
*/
|
|
251
|
-
begin() {
|
|
252
|
-
return new DequeIterator<E>(0, this);
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
/**
|
|
256
|
-
* The `end()` function returns a new `DequeIterator` object with the size and reference to the
|
|
257
|
-
* current deque.
|
|
258
|
-
* @returns A new instance of the DequeIterator class is being returned.
|
|
165
|
+
* The below function is a generator that yields elements from a collection one by one.
|
|
259
166
|
*/
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
* the deque and iterates in reverse direction.
|
|
267
|
-
* @returns A new instance of the DequeIterator class is being returned.
|
|
268
|
-
*/
|
|
269
|
-
reverseBegin() {
|
|
270
|
-
return new DequeIterator<E>(this.size - 1, this, IterateDirection.REVERSE);
|
|
167
|
+
* begin(): Generator<E> {
|
|
168
|
+
let index = 0;
|
|
169
|
+
while (index < this.size) {
|
|
170
|
+
yield this.getAt(index);
|
|
171
|
+
index++;
|
|
172
|
+
}
|
|
271
173
|
}
|
|
272
174
|
|
|
273
175
|
/**
|
|
274
|
-
* The
|
|
275
|
-
*
|
|
276
|
-
* @returns A new instance of the DequeIterator class is being returned.
|
|
176
|
+
* The function `reverseBegin()` is a generator that yields elements in reverse order starting from
|
|
177
|
+
* the last element.
|
|
277
178
|
*/
|
|
278
|
-
|
|
279
|
-
|
|
179
|
+
* reverseBegin(): Generator<E> {
|
|
180
|
+
let index = this.size - 1;
|
|
181
|
+
while (index >= 0) {
|
|
182
|
+
yield this.getAt(index);
|
|
183
|
+
index--;
|
|
184
|
+
}
|
|
280
185
|
}
|
|
281
186
|
|
|
282
187
|
/**
|
|
@@ -431,7 +336,7 @@ export class Deque<E> {
|
|
|
431
336
|
* @returns The element at the specified position in the data structure is being returned.
|
|
432
337
|
*/
|
|
433
338
|
getAt(pos: number): E {
|
|
434
|
-
rangeCheck
|
|
339
|
+
rangeCheck(pos, 0, this.size - 1);
|
|
435
340
|
const {
|
|
436
341
|
bucketIndex,
|
|
437
342
|
indexInBucket
|
|
@@ -456,7 +361,7 @@ export class Deque<E> {
|
|
|
456
361
|
* position in the data structure.
|
|
457
362
|
*/
|
|
458
363
|
setAt(pos: number, element: E) {
|
|
459
|
-
rangeCheck
|
|
364
|
+
rangeCheck(pos, 0, this.size - 1);
|
|
460
365
|
const {
|
|
461
366
|
bucketIndex,
|
|
462
367
|
indexInBucket
|
|
@@ -486,7 +391,7 @@ export class Deque<E> {
|
|
|
486
391
|
*/
|
|
487
392
|
insertAt(pos: number, element: E, num = 1) {
|
|
488
393
|
const length = this.size;
|
|
489
|
-
rangeCheck
|
|
394
|
+
rangeCheck(pos, 0, length);
|
|
490
395
|
if (pos === 0) {
|
|
491
396
|
while (num--) this.unshift(element);
|
|
492
397
|
} else if (pos === this.size) {
|
|
@@ -550,7 +455,7 @@ export class Deque<E> {
|
|
|
550
455
|
* @returns The size of the data structure after the deletion operation is performed.
|
|
551
456
|
*/
|
|
552
457
|
deleteAt(pos: number) {
|
|
553
|
-
rangeCheck
|
|
458
|
+
rangeCheck(pos, 0, this.size - 1);
|
|
554
459
|
if (pos === 0) this.shift();
|
|
555
460
|
else if (pos === this.size - 1) this.pop();
|
|
556
461
|
else {
|
|
@@ -605,50 +510,6 @@ export class Deque<E> {
|
|
|
605
510
|
return this.size;
|
|
606
511
|
}
|
|
607
512
|
|
|
608
|
-
/**
|
|
609
|
-
* Time Complexity: O(n)
|
|
610
|
-
* Space Complexity: O(1)
|
|
611
|
-
*/
|
|
612
|
-
|
|
613
|
-
/**
|
|
614
|
-
* Time Complexity: O(n)
|
|
615
|
-
* Space Complexity: O(1)
|
|
616
|
-
*
|
|
617
|
-
* The function deletes an element from a deque using an iterator and returns the next iterator.
|
|
618
|
-
* @param iter - The parameter `iter` is of type `DequeIterator<E>`. It represents an iterator object
|
|
619
|
-
* that is used to iterate over elements in a deque (double-ended queue).
|
|
620
|
-
* @returns the updated iterator after deleting an element from the deque.
|
|
621
|
-
*/
|
|
622
|
-
deleteByIterator(iter: DequeIterator<E>) {
|
|
623
|
-
const index = iter.index;
|
|
624
|
-
this.deleteAt(index);
|
|
625
|
-
iter = iter.next();
|
|
626
|
-
return iter;
|
|
627
|
-
}
|
|
628
|
-
|
|
629
|
-
/**
|
|
630
|
-
* Time Complexity: O(n)
|
|
631
|
-
* Space Complexity: O(1)
|
|
632
|
-
*/
|
|
633
|
-
|
|
634
|
-
/**
|
|
635
|
-
* Time Complexity: O(n)
|
|
636
|
-
* Space Complexity: O(1)
|
|
637
|
-
*
|
|
638
|
-
* The function `findIterator` searches for an element in a deque and returns an iterator pointing to
|
|
639
|
-
* the element if found, otherwise it returns an iterator pointing to the end of the deque.
|
|
640
|
-
* @param {E} element - The `element` parameter is the element that you want to find in the deque.
|
|
641
|
-
* @returns The method `findIterator(element: E)` returns a `DequeIterator<E>` object.
|
|
642
|
-
*/
|
|
643
|
-
findIterator(element: E) {
|
|
644
|
-
for (let i = 0; i < this.size; ++i) {
|
|
645
|
-
if (this.getAt(i) === element) {
|
|
646
|
-
return new DequeIterator<E>(i, this);
|
|
647
|
-
}
|
|
648
|
-
}
|
|
649
|
-
return this.end();
|
|
650
|
-
}
|
|
651
|
-
|
|
652
513
|
/**
|
|
653
514
|
* Time Complexity: O(n)
|
|
654
515
|
* Space Complexity: O(1)
|
|
@@ -5,42 +5,42 @@ import { magnitude } from '../../../utils';
|
|
|
5
5
|
import { isCompetitor } from '../../../config';
|
|
6
6
|
|
|
7
7
|
const suite = new Benchmark.Suite();
|
|
8
|
-
const {
|
|
8
|
+
const { MILLION } = magnitude;
|
|
9
9
|
|
|
10
|
-
suite.add(`${
|
|
10
|
+
suite.add(`${MILLION.toLocaleString()} set`, () => {
|
|
11
11
|
const hm = new HashMap<number, number>();
|
|
12
12
|
|
|
13
|
-
for (let i = 0; i <
|
|
13
|
+
for (let i = 0; i < MILLION; i++) {
|
|
14
14
|
hm.set(i, i);
|
|
15
15
|
}
|
|
16
16
|
});
|
|
17
17
|
if (isCompetitor) {
|
|
18
|
-
suite.add(`${
|
|
18
|
+
suite.add(`${MILLION.toLocaleString()} CPT set`, () => {
|
|
19
19
|
const hm = new CHashMap<number, number>();
|
|
20
20
|
|
|
21
|
-
for (let i = 0; i <
|
|
21
|
+
for (let i = 0; i < MILLION; i++) {
|
|
22
22
|
hm.setElement(i, i);
|
|
23
23
|
}
|
|
24
24
|
});
|
|
25
25
|
}
|
|
26
|
-
suite.add(`${
|
|
26
|
+
suite.add(`${MILLION.toLocaleString()} set & get`, () => {
|
|
27
27
|
const hm = new HashMap<number, number>();
|
|
28
28
|
|
|
29
|
-
for (let i = 0; i <
|
|
29
|
+
for (let i = 0; i < MILLION; i++) {
|
|
30
30
|
hm.set(i, i);
|
|
31
31
|
}
|
|
32
|
-
for (let i = 0; i <
|
|
32
|
+
for (let i = 0; i < MILLION; i++) {
|
|
33
33
|
hm.get(i);
|
|
34
34
|
}
|
|
35
35
|
});
|
|
36
36
|
if (isCompetitor) {
|
|
37
|
-
suite.add(`${
|
|
37
|
+
suite.add(`${MILLION.toLocaleString()} CPT set & get`, () => {
|
|
38
38
|
const hm = new CHashMap<number, number>();
|
|
39
39
|
|
|
40
|
-
for (let i = 0; i <
|
|
40
|
+
for (let i = 0; i < MILLION; i++) {
|
|
41
41
|
hm.setElement(i, i);
|
|
42
42
|
}
|
|
43
|
-
for (let i = 0; i <
|
|
43
|
+
for (let i = 0; i < MILLION; i++) {
|
|
44
44
|
hm.getElementByKey(i);
|
|
45
45
|
}
|
|
46
46
|
});
|
|
@@ -25,17 +25,20 @@ const reportDistPath = path.join(parentDirectory, 'benchmark');
|
|
|
25
25
|
|
|
26
26
|
const testDir = path.join(__dirname, 'data-structures');
|
|
27
27
|
const allFiles = fastGlob.sync(path.join(testDir, '**', '*.test.ts'));
|
|
28
|
-
let testFiles: string[]
|
|
28
|
+
let testFiles: string[];
|
|
29
|
+
|
|
30
|
+
let isIndividual = false;
|
|
29
31
|
if (args.length > 0) {
|
|
30
32
|
console.log(`arguments: ${args.join(' ')}`)
|
|
31
33
|
|
|
32
34
|
testFiles = allFiles.filter(file =>
|
|
33
35
|
args.every(word => file.includes(word))
|
|
34
36
|
);
|
|
35
|
-
|
|
37
|
+
isIndividual = true;
|
|
36
38
|
console.log(`${testFiles.map(file => coloredLabeled('Matched', file)).join(`
|
|
37
39
|
`)}`);
|
|
38
40
|
} else {
|
|
41
|
+
isIndividual = false;
|
|
39
42
|
testFiles = allFiles;
|
|
40
43
|
}
|
|
41
44
|
|
|
@@ -129,7 +132,7 @@ const composeReport = () => {
|
|
|
129
132
|
html += `</div>
|
|
130
133
|
</body>
|
|
131
134
|
</html>`;
|
|
132
|
-
replaceMarkdownContent(
|
|
135
|
+
if (!isIndividual) replaceMarkdownContent(
|
|
133
136
|
'[//]: # (No deletion!!! Start of Replace Section)', // Start tag
|
|
134
137
|
'[//]: # (No deletion!!! End of Replace Section)', // end identifier
|
|
135
138
|
htmlTables // New content to be inserted
|
|
@@ -172,15 +172,14 @@ describe('HashMap', () => {
|
|
|
172
172
|
stdMap.forEach((value, key) => {
|
|
173
173
|
if (index === 0) {
|
|
174
174
|
expect(hashMap.first).toEqual([key, value]);
|
|
175
|
-
expect(hashMap.begin.
|
|
175
|
+
expect(hashMap.begin().next().value).toEqual([key, value]);
|
|
176
176
|
} else if (index === hashMap.size - 1) {
|
|
177
177
|
expect(hashMap.last).toEqual([key, value]);
|
|
178
|
-
expect(hashMap.reverseBegin.
|
|
178
|
+
expect(hashMap.reverseBegin().next().value).toEqual([key, value]);
|
|
179
179
|
} else if (index <= 1000) {
|
|
180
180
|
expect(hashMap.getAt(index)).toEqual([key, value]);
|
|
181
181
|
}
|
|
182
182
|
expect(hashMap.get(key)).toEqual(value);
|
|
183
|
-
expect(hashMap.getIterator(key).current[1]).toEqual(value);
|
|
184
183
|
index++;
|
|
185
184
|
});
|
|
186
185
|
}
|
|
@@ -210,8 +209,8 @@ describe('HashMap', () => {
|
|
|
210
209
|
test('should iterate correctly with reverse iterators', () => {
|
|
211
210
|
hashMap.set('key1', 'value1');
|
|
212
211
|
hashMap.set('key2', 'value2');
|
|
213
|
-
const iterator = hashMap.reverseBegin;
|
|
214
|
-
expect(iterator.next().
|
|
212
|
+
const iterator = hashMap.reverseBegin();
|
|
213
|
+
expect(iterator.next().value).toEqual(['key2', 'value2']);
|
|
215
214
|
});
|
|
216
215
|
|
|
217
216
|
test('should return the last element', () => {
|
|
@@ -419,4 +419,32 @@ describe('Deque', () => {
|
|
|
419
419
|
expect(deque.indexOf(2)).toBe(1);
|
|
420
420
|
expect(deque.indexOf(4)).toBe(-1);
|
|
421
421
|
});
|
|
422
|
+
|
|
423
|
+
|
|
424
|
+
//Test begin method
|
|
425
|
+
describe('begin()', () => {
|
|
426
|
+
it('should return an iterator at the beginning of the deque', () => {
|
|
427
|
+
deque.push(1);
|
|
428
|
+
deque.push(2);
|
|
429
|
+
deque.push(3);
|
|
430
|
+
|
|
431
|
+
const iterator = deque.begin();
|
|
432
|
+
|
|
433
|
+
expect(iterator.next().value).toBe(1);
|
|
434
|
+
});
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
// Test the reverse Begin method
|
|
438
|
+
describe('reverseBegin()', () => {
|
|
439
|
+
it('should return a reverse iterator at the beginning of the deque', () => {
|
|
440
|
+
deque.push(1);
|
|
441
|
+
deque.push(2);
|
|
442
|
+
deque.push(3);
|
|
443
|
+
|
|
444
|
+
const iterator = deque.reverseBegin();
|
|
445
|
+
|
|
446
|
+
expect(iterator.next().value).toBe(3);
|
|
447
|
+
});
|
|
448
|
+
});
|
|
449
|
+
|
|
422
450
|
});
|