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